diff --git a/frame/controller/dockitemmanager.cpp b/frame/controller/dockitemmanager.cpp index c5f24eee3..1fc483664 100644 --- a/frame/controller/dockitemmanager.cpp +++ b/frame/controller/dockitemmanager.cpp @@ -24,7 +24,6 @@ #include "item/launcheritem.h" #include "item/pluginsitem.h" #include "item/traypluginitem.h" -#include "util/docksettings.h" #include #include diff --git a/frame/panel/mainpanelcontrol.cpp b/frame/panel/mainpanelcontrol.cpp index b3308586f..09a2560da 100755 --- a/frame/panel/mainpanelcontrol.cpp +++ b/frame/panel/mainpanelcontrol.cpp @@ -21,7 +21,6 @@ #include "mainpanelcontrol.h" #include "../item/dockitem.h" -#include "util/docksettings.h" #include "../item/placeholderitem.h" #include "../item/components/appdrag.h" #include "../item/appitem.h" diff --git a/frame/util/docksettings.cpp b/frame/util/docksettings.cpp deleted file mode 100644 index 05ab87f54..000000000 --- a/frame/util/docksettings.cpp +++ /dev/null @@ -1,966 +0,0 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * - * Maintainer: sbw - * zhaolong - * - * 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 "docksettings.h" -#include "item/appitem.h" -#include "util/utils.h" -#include "controller/dockitemmanager.h" - -#include -#include -#include - -#include -#include - -#define FASHION_MODE_PADDING 30 -#define MAINWINDOW_MARGIN 10 - -#define FASHION_DEFAULT_HEIGHT 72 -#define EffICIENT_DEFAULT_HEIGHT 40 -#define WINDOW_MAX_SIZE 100 -#define WINDOW_MIN_SIZE 40 - -DWIDGET_USE_NAMESPACE - -extern const QPoint rawXPosition(const QPoint &scaledPos); - -static QGSettings *GSettingsByMenu() -{ - static QGSettings settings("com.deepin.dde.dock.module.menu"); - return &settings; -} - -static QGSettings *GSettingsByTrash() -{ - static QGSettings settings("com.deepin.dde.dock.module.trash"); - return &settings; -} - -DockSettings::DockSettings(QWidget *parent) - : QObject(parent) - , m_dockInter(new DBusDock("com.deepin.dde.daemon.Dock", "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this)) - , m_menuVisible(true) - , m_autoHide(true) - , m_opacity(0.4) - , m_fashionModeAct(tr("Fashion Mode"), this) - , m_efficientModeAct(tr("Efficient Mode"), this) - , m_topPosAct(tr("Top"), this) - , m_bottomPosAct(tr("Bottom"), this) - , m_leftPosAct(tr("Left"), this) - , m_rightPosAct(tr("Right"), this) - , m_keepShownAct(tr("Keep Shown"), this) - , m_keepHiddenAct(tr("Keep Hidden"), this) - , m_smartHideAct(tr("Smart Hide"), 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_isMouseMoveCause(false) - , m_mouseCauseDockScreen(nullptr) -{ - m_settingsMenu.setAccessibleName("settingsmenu"); - checkService(); - - 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()); - m_hideState = Dock::HideState(m_dockInter->hideState()); - DockItem::setDockPosition(m_position); - qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position)); - DockItem::setDockDisplayMode(m_displayMode); - qApp->setProperty(PROP_DISPLAY_MODE, QVariant::fromValue(m_displayMode)); - - m_fashionModeAct.setCheckable(true); - m_efficientModeAct.setCheckable(true); - m_topPosAct.setCheckable(true); - m_bottomPosAct.setCheckable(true); - m_leftPosAct.setCheckable(true); - m_rightPosAct.setCheckable(true); - m_keepShownAct.setCheckable(true); - m_keepHiddenAct.setCheckable(true); - m_smartHideAct.setCheckable(true); - - QMenu *modeSubMenu = new QMenu(&m_settingsMenu); - modeSubMenu->setAccessibleName("modesubmenu"); - modeSubMenu->addAction(&m_fashionModeAct); - modeSubMenu->addAction(&m_efficientModeAct); - QAction *modeSubMenuAct = new QAction(tr("Mode"), this); - modeSubMenuAct->setMenu(modeSubMenu); - - QMenu *locationSubMenu = new QMenu(&m_settingsMenu); - locationSubMenu->setAccessibleName("locationsubmenu"); - locationSubMenu->addAction(&m_topPosAct); - locationSubMenu->addAction(&m_bottomPosAct); - locationSubMenu->addAction(&m_leftPosAct); - locationSubMenu->addAction(&m_rightPosAct); - QAction *locationSubMenuAct = new QAction(tr("Location"), this); - locationSubMenuAct->setMenu(locationSubMenu); - - QMenu *statusSubMenu = new QMenu(&m_settingsMenu); - statusSubMenu->setAccessibleName("statussubmenu"); - statusSubMenu->addAction(&m_keepShownAct); - statusSubMenu->addAction(&m_keepHiddenAct); - statusSubMenu->addAction(&m_smartHideAct); - QAction *statusSubMenuAct = new QAction(tr("Status"), this); - statusSubMenuAct->setMenu(statusSubMenu); - - m_hideSubMenu = new QMenu(&m_settingsMenu); - m_hideSubMenu->setAccessibleName("pluginsmenu"); - QAction *hideSubMenuAct = new QAction(tr("Plugins"), this); - hideSubMenuAct->setMenu(m_hideSubMenu); - - m_settingsMenu.addAction(modeSubMenuAct); - m_settingsMenu.addAction(locationSubMenuAct); - m_settingsMenu.addAction(statusSubMenuAct); - m_settingsMenu.addAction(hideSubMenuAct); - m_settingsMenu.setTitle("Settings Menu"); - - connect(&m_settingsMenu, &QMenu::triggered, this, &DockSettings::menuActionClicked); - connect(GSettingsByMenu(), &QGSettings::changed, this, &DockSettings::onGSettingsChanged); - connect(m_dockInter, &DBusDock::PositionChanged, this, &DockSettings::onPositionChanged); - connect(m_dockInter, &DBusDock::DisplayModeChanged, this, &DockSettings::onDisplayModeChanged); - connect(m_dockInter, &DBusDock::HideModeChanged, this, &DockSettings::hideModeChanged, Qt::QueuedConnection); - connect(m_dockInter, &DBusDock::HideStateChanged, this, &DockSettings::hideStateChanged); - connect(m_dockInter, &DBusDock::ServiceRestarted, this, &DockSettings::resetFrontendGeometry); - connect(m_dockInter, &DBusDock::OpacityChanged, this, &DockSettings::onOpacityChanged); - connect(m_dockInter, &DBusDock::WindowSizeEfficientChanged, this, &DockSettings::onWindowSizeChanged); - connect(m_dockInter, &DBusDock::WindowSizeFashionChanged, this, &DockSettings::onWindowSizeChanged); - - connect(m_itemManager, &DockItemManager::itemInserted, this, &DockSettings::dockItemCountChanged, Qt::QueuedConnection); - connect(m_itemManager, &DockItemManager::itemRemoved, this, &DockSettings::dockItemCountChanged, Qt::QueuedConnection); - connect(m_itemManager, &DockItemManager::trayVisableCountChanged, this, &DockSettings::trayVisableCountChanged, Qt::QueuedConnection); - - connect(m_displayInter, &DisplayInter::PrimaryRectChanged, this, &DockSettings::onPrimaryScreenChanged, Qt::QueuedConnection); - connect(m_displayInter, &DisplayInter::ScreenHeightChanged, this, &DockSettings::onPrimaryScreenChanged, Qt::QueuedConnection); - connect(m_displayInter, &DisplayInter::ScreenWidthChanged, this, &DockSettings::onPrimaryScreenChanged, Qt::QueuedConnection); - connect(m_displayInter, &DisplayInter::PrimaryChanged, this, &DockSettings::onPrimaryScreenChanged, Qt::QueuedConnection); - connect(m_displayInter, &DisplayInter::MonitorsChanged, this, &DockSettings::onMonitorListChanged); - connect(GSettingsByTrash(), &QGSettings::changed, this, &DockSettings::onTrashGSettingsChanged); - QTimer::singleShot(0, this, [ = ] {onGSettingsChanged("enable");}); - - DApplication *app = qobject_cast(qApp); - if (app) { - connect(app, &DApplication::iconThemeChanged, this, &DockSettings::gtkIconThemeChanged); - } - - calculateMultiScreensPos(); - calculateWindowConfig(); - resetFrontendGeometry(); - - QTimer::singleShot(0, this, [ = ] {onOpacityChanged(m_dockInter->opacity());}); - QTimer::singleShot(0, this, [ = ] { - onGSettingsChanged("enable"); - }); -} - -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; - return settings; -} - -const QRect DockSettings::primaryRect() const -{ - QRect rect = m_primaryRawRect; - qreal scale = qApp->primaryScreen()->devicePixelRatio(); - - rect.setWidth(std::round(qreal(rect.width()) / scale)); - rect.setHeight(std::round(qreal(rect.height()) / scale)); - - return rect; -} - -const QRect DockSettings::currentRect(const bool beNarrow) -{ - QRect rect; - QString currentScrName; - if (!beNarrow) { - if (m_isMouseMoveCause) { - rect = m_mouseCauseDockScreen->rect(); - currentScrName = m_mouseCauseDockScreen->name(); - } else { - 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(); - currentScrName = monitor->name(); - if (monitor->isPrimary()) - break; - } - } - } - - m_currentScreen = currentScrName; - m_currentRawRect = rect; - - } else { - rect = m_currentRawRect; - } - - 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) - return 0; - - return 10; -} - -//const QSize DockSettings::panelSize() const -//{ -// return m_mainWindowSize; -//} - -const QRect DockSettings::windowRect(const Position position, const bool hide, const bool beNarrow) -{ - QSize size = m_mainWindowSize; - if (hide) { - switch (position) { - case Top: - case Bottom: size.setHeight(0); break; - case Left: - case Right: size.setWidth(0); break; - } - } - - const QRect primaryRect = this->currentRect(beNarrow); - const int offsetX = (primaryRect.width() - size.width()) / 2; - const int offsetY = (primaryRect.height() - size.height()) / 2; - int margin = hide ? 0 : this->dockMargin(); - QPoint p(0, 0); - switch (position) { - case Top: - p = QPoint(offsetX, margin); - break; - case Left: - p = QPoint(margin, offsetY); - break; - case Right: - p = QPoint(primaryRect.width() - size.width() - margin, offsetY); - break; - case Bottom: - p = QPoint(offsetX, primaryRect.height() - size.height() - margin); - break; - } - - return QRect(primaryRect.topLeft() + p, size); -} - -void DockSettings::showDockSettingsMenu() -{ - QTimer::singleShot(0, this, [ = ] { - onGSettingsChanged("enable"); - }); - - m_autoHide = false; - - bool hasComposite = DWindowManagerHelper::instance()->hasComposite(); - - // create actions - QList actions; - for (auto *p : m_itemManager->pluginList()) { - if (!p->pluginIsAllowDisable()) - continue; - - const bool enable = !p->pluginIsDisable(); - const QString &name = p->pluginName(); - const QString &display = p->pluginDisplayName(); - - if (!m_trashPluginShow && name == "trash") { - continue; - } - - if (name == "multitasking" && !hasComposite) { - continue; - } - - QAction *act = new QAction(display, this); - act->setCheckable(true); - act->setChecked(enable); - act->setData(name); - - actions << act; - } - - // sort by name - std::sort(actions.begin(), actions.end(), [](QAction * a, QAction * b) -> bool { - return a->data().toString() > b->data().toString(); - }); - - // add actions - qDeleteAll(m_hideSubMenu->actions()); - for (auto act : actions) - m_hideSubMenu->addAction(act); - - m_fashionModeAct.setChecked(m_displayMode == Fashion); - m_efficientModeAct.setChecked(m_displayMode == Efficient); - m_topPosAct.setChecked(m_position == Top); - m_bottomPosAct.setChecked(m_position == Bottom); - m_leftPosAct.setChecked(m_position == Left); - m_rightPosAct.setChecked(m_position == Right); - m_keepShownAct.setChecked(m_hideMode == KeepShowing); - m_keepHiddenAct.setChecked(m_hideMode == KeepHidden); - m_smartHideAct.setChecked(m_hideMode == SmartHide); - - m_settingsMenu.exec(QCursor::pos()); - - setAutoHide(true); -} - -void DockSettings::updateGeometry() -{ - -} - -void DockSettings::setAutoHide(const bool autoHide) -{ - if (m_autoHide == autoHide) - return; - - m_autoHide = autoHide; - emit autoHideChanged(m_autoHide); -} - -void DockSettings::menuActionClicked(QAction *action) -{ - Q_ASSERT(action); - - if (action == &m_fashionModeAct) - return m_dockInter->setDisplayMode(Fashion); - if (action == &m_efficientModeAct) - return m_dockInter->setDisplayMode(Efficient); - - if (action == &m_topPosAct) - return m_dockInter->setPosition(Top); - if (action == &m_bottomPosAct) - return m_dockInter->setPosition(Bottom); - if (action == &m_leftPosAct) - return m_dockInter->setPosition(Left); - if (action == &m_rightPosAct) - return m_dockInter->setPosition(Right); - if (action == &m_keepShownAct) - return m_dockInter->setHideMode(KeepShowing); - if (action == &m_keepHiddenAct) - return m_dockInter->setHideMode(KeepHidden); - if (action == &m_smartHideAct) - return m_dockInter->setHideMode(SmartHide); - - // check plugin hide menu. - const QString &data = action->data().toString(); - if (data.isEmpty()) - return; - for (auto *p : m_itemManager->pluginList()) { - if (p->pluginName() == data) - return p->pluginStateSwitched(); - } -} - -void DockSettings::onGSettingsChanged(const QString &key) -{ - if (key != "enable") { - return; - } - - QGSettings *setting = GSettingsByMenu(); - - if (setting->keys().contains("enable")) { - const bool isEnable = GSettingsByMenu()->keys().contains("enable") && GSettingsByMenu()->get("enable").toBool(); - m_menuVisible = isEnable && setting->get("enable").toBool(); - } -} - -void DockSettings::onPositionChanged() -{ - const Position nextPos = Dock::Position(m_dockInter->position()); - - if (m_position == nextPos) - return; - m_position = nextPos; - - m_isMouseMoveCause = false; - // 位置改变 重新计算可停靠任务栏的位置 - calculateMultiScreensPos(); - - // 通知主窗口改变位置 - emit positionChanged(); -} - -void DockSettings::onDisplayModeChanged() -{ -// qDebug() << Q_FUNC_INFO; - m_displayMode = Dock::DisplayMode(m_dockInter->displayMode()); - DockItem::setDockDisplayMode(m_displayMode); - qApp->setProperty(PROP_DISPLAY_MODE, QVariant::fromValue(m_displayMode)); - - emit displayModeChanegd(); - calculateWindowConfig(); - - //QTimer::singleShot(1, m_itemManager, &DockItemManager::sortPluginItems); -} - -void DockSettings::hideModeChanged() -{ -// qDebug() << Q_FUNC_INFO; - m_hideMode = Dock::HideMode(m_dockInter->hideMode()); - - emit windowHideModeChanged(); -} - -void DockSettings::hideStateChanged() -{ -// qDebug() << Q_FUNC_INFO; - const Dock::HideState state = Dock::HideState(m_dockInter->hideState()); - - if (state == Dock::Unknown) - return; - - m_hideState = state; - - emit windowVisibleChanged(); -} - -void DockSettings::dockItemCountChanged() -{ -// emit windowGeometryChanged(); -} - -void DockSettings::onPrimaryScreenChanged() -{ -// qDebug() << Q_FUNC_INFO; - m_primaryRawRect = m_displayInter->primaryRect(); - m_screenRawHeight = m_displayInter->screenHeight(); - m_screenRawWidth = m_displayInter->screenWidth(); - - //为了防止当后端发送错误值,然后发送正确值时,任务栏没有移动在相应的位置 - //当qt没有获取到屏幕资源时候,move函数会失效。可以直接return - if (m_screenRawHeight == 0 || m_screenRawWidth == 0) { - return; - } - calculateMultiScreensPos(); - emit primaryScreenChanged(); - calculateWindowConfig(); - - // 主屏切换时,如果缩放比例不一样,需要刷新item的图标(bug:3176) - m_itemManager->refershItemsIcon(); -} - -void DockSettings::resetFrontendGeometry() -{ - const QRect r = windowRect(m_position); - const qreal ratio = dockRatio(); - const QPoint p = rawXPosition(r.topLeft()); - const uint w = r.width() * ratio; - const uint h = r.height() * ratio; - - m_frontendRect = QRect(p.x(), p.y(), w, h); - m_dockInter->SetFrontendWindowRect(p.x(), p.y(), w, h); -} - -void DockSettings::updateFrontendGeometry() -{ - resetFrontendGeometry(); -} - -bool DockSettings::setDockScreen(const QString &scrName) -{ - QList monitors = m_monitors.keys(); - for (Monitor *monitor : monitors) { - if (monitor && monitor->name() == scrName) { - m_mouseCauseDockScreen = monitor; - break; - } - } - - bool canBeDock = false; - switch (m_position) { - case Top: - canBeDock = m_mouseCauseDockScreen->dockPosition().topDock; - break; - case Right: - canBeDock = m_mouseCauseDockScreen->dockPosition().rightDock; - break; - case Bottom: - canBeDock = m_mouseCauseDockScreen->dockPosition().bottomDock; - break; - case Left: - canBeDock = m_mouseCauseDockScreen->dockPosition().leftDock; - break; - } - m_isMouseMoveCause = canBeDock; - - posChangedUpdateSettings(); - - return canBeDock; -} - -void DockSettings::onOpacityChanged(const double value) -{ - if (m_opacity == value) return; - - m_opacity = value; - - emit opacityChanged(value * 255); -} - -void DockSettings::trayVisableCountChanged(const int &count) -{ - emit trayCountChanged(); -} - -void DockSettings::calculateWindowConfig() -{ - if (m_displayMode == Dock::Efficient) { - 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); - } - - switch (m_position) { - case Top: - case Bottom: - m_mainWindowSize.setHeight(m_dockWindowSize); - m_mainWindowSize.setWidth(currentRect().width()); - break; - - case Left: - case Right: - m_mainWindowSize.setHeight(currentRect().height()); - m_mainWindowSize.setWidth(m_dockWindowSize); - break; - } - } else if (m_displayMode == Dock::Fashion) { - 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); - } - - switch (m_position) { - case Top: - case Bottom: { - m_mainWindowSize.setHeight(m_dockWindowSize); - m_mainWindowSize.setWidth(this->currentRect().width() - MAINWINDOW_MARGIN * 2); - break; - } - case Left: - case Right: { - m_mainWindowSize.setHeight(this->currentRect().height() - MAINWINDOW_MARGIN * 2); - m_mainWindowSize.setWidth(m_dockWindowSize); - break; - } - } - } else { - Q_ASSERT(false); - } - - resetFrontendGeometry(); -} - -void DockSettings::gtkIconThemeChanged() -{ - qDebug() << Q_FUNC_INFO; - m_itemManager->refershItemsIcon(); -} - -qreal DockSettings::dockRatio() const -{ - QScreen const *screen = Utils::screenAtByScaled(m_frontendRect.center()); - - return screen ? screen->devicePixelRatio() : qApp->devicePixelRatio(); -} - -void DockSettings::onWindowSizeChanged() -{ - calculateWindowConfig(); - emit windowGeometryChanged(); -} - -void DockSettings::checkService() -{ - // com.deepin.dde.daemon.Dock服务比dock晚启动,导致dock启动后的状态错误 - - QString serverName = "com.deepin.dde.daemon.Dock"; - 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()) { - - m_dockInter = new DBusDock(serverName, "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this); - onPositionChanged(); - onDisplayModeChanged(); - hideModeChanged(); - hideStateChanged(); - onOpacityChanged(m_dockInter->opacity()); - onWindowSizeChanged(); - - disconnect(ifc); - } - }); - } -} - -void DockSettings::posChangedUpdateSettings() -{ - DockItem::setDockPosition(m_position); - qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position)); - - calculateWindowConfig(); - - m_itemManager->refershItemsIcon(); -} - -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(mon, &Monitor::geometryChanged, this, [ = ] { - calculateWindowConfig(); - emit windowGeometryChanged(); - emit requestUpdateRegionWatch(); - }); - - 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; - // 左右拼 - if (s1->bottom() > s2->top() && s1->top() < s2->bottom()) { - // 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; - } - } - // 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; - } - } - } - // 上下拼 - if (s1->right() > s2->left() && s1->left() < s2->right()) { - // s1上 s2下 - if (s1->bottom() == s2->top()) { - isAligment = (s1->bottomLeft() == s2->topLeft()) - && (s1->bottomRight() == s2->topRight()); - if (isAligment) { - s1->dockPosition().bottomDock = false; - s2->dockPosition().topDock = false; - } - } - // s1下 s2上 - if (s1->top() == s2->bottom()) { - isAligment = (s1->topLeft() == s2->bottomLeft()) - && (s1->topRight() == s2->bottomRight()); - if (isAligment) { - s1->dockPosition().topDock = false; - 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") { - return ; - } - - QGSettings *setting = GSettingsByTrash(); - - if (setting->keys().contains("enable")) { - 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); - - QMapIterator iterator(m_monitors); - while (iterator.hasNext()) { - iterator.next(); - Monitor *monitor = iterator.key(); - if (monitor) { - m_mouseCauseDockScreen = monitor; - break; - } - } -} diff --git a/frame/util/docksettings.h b/frame/util/docksettings.h deleted file mode 100644 index e030e61a5..000000000 --- a/frame/util/docksettings.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * - * Maintainer: sbw - * zhaolong - * - * 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 DOCKSETTINGS_H -#define DOCKSETTINGS_H - -#include "constants.h" -#include "monitor.h" - -#include -#include - -#include -#include - -#include -#include - -using namespace Dock; -using DBusDock = com::deepin::dde::daemon::Dock; -using DisplayInter = com::deepin::daemon::Display; - -class DockItemManager; -class DockSettings : public QObject -{ - Q_OBJECT - -public: - static DockSettings &Instance(); - - inline DisplayMode displayMode() const { return m_displayMode; } - inline HideMode hideMode() const { return m_hideMode; } - inline HideState hideState() const { return m_hideState; } - inline Position position() const { return m_position; } - inline int screenRawHeight() const { return m_screenRawHeight; } - inline int screenRawWidth() const { return m_screenRawWidth; } - inline int expandTimeout() const { return m_dockInter->showTimeout(); } - inline int narrowTimeout() const { return 100; } - inline bool autoHide() const { return m_autoHide; } - const QRect primaryRect() const; - const QRect currentRect(const bool beNarrow = false); - 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; } - const int dockMargin() const; - -// const QSize panelSize() const; - const QRect windowRect(const Position position, const bool hide = false, const bool beNarrow = false); - qreal dockRatio() const; - - void showDockSettingsMenu(); - void updateFrontendGeometry(); - - bool setDockScreen(const QString &scrName); - QString ¤tDockScreen() { return m_currentScreen; } - - void posChangedUpdateSettings(); - void calculateWindowConfig(); - - QSize m_mainWindowSize; - DBusDock *m_dockInter; - bool m_menuVisible; - -signals: - void primaryScreenChanged() const; - void positionChanged() const; - void autoHideChanged(const bool autoHide) const; - void displayModeChanegd() const; - void windowVisibleChanged() const; - void windowHideModeChanged() const; - void windowGeometryChanged() const; - void opacityChanged(const quint8 value) const; - void trayCountChanged() const; - // 分标率发生变化,需要更新XEventMonitor的监视区域 - void requestUpdateRegionWatch(); - -public slots: - void updateGeometry(); - void setAutoHide(const bool autoHide); - -private slots: - void menuActionClicked(QAction *action); - void onGSettingsChanged(const QString &key); - void onPositionChanged(); - void onDisplayModeChanged(); - void hideModeChanged(); - void hideStateChanged(); - void dockItemCountChanged(); - void onPrimaryScreenChanged(); - void resetFrontendGeometry(); - void onOpacityChanged(const double value); - void trayVisableCountChanged(const int &count); - void onWindowSizeChanged(); - void onTrashGSettingsChanged(const QString &key); - void onMonitorListChanged(const QList &mons); - -private: - explicit DockSettings(QWidget *parent = nullptr); - DockSettings(DockSettings const &) = delete; - DockSettings operator =(DockSettings const &) = delete; - - 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; - int m_screenRawHeight; - int m_screenRawWidth; - double m_opacity; - int m_dockMargin; - QSet m_forbidPositions; - Position m_position; - HideMode m_hideMode; - HideState m_hideState; - DisplayMode m_displayMode; - QRect m_primaryRawRect; - QRect m_currentRawRect; - QRect m_frontendRect; - - QMenu m_settingsMenu; - QMenu *m_hideSubMenu; - QAction m_fashionModeAct; - QAction m_efficientModeAct; - QAction m_topPosAct; - QAction m_bottomPosAct; - QAction m_leftPosAct; - QAction m_rightPosAct; - QAction m_keepShownAct; - QAction m_keepHiddenAct; - QAction m_smartHideAct; - - DisplayInter *m_displayInter; - DockItemManager *m_itemManager; - bool m_trashPluginShow; - - QMap m_monitors; - bool m_isMouseMoveCause; - Monitor *m_mouseCauseDockScreen; - QString m_currentScreen; -}; - -#endif // DOCKSETTINGS_H diff --git a/frame/util/menuworker.cpp b/frame/util/menuworker.cpp new file mode 100644 index 000000000..fa7875378 --- /dev/null +++ b/frame/util/menuworker.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2018 ~ 2028 Deepin 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 "menuworker.h" +#include "controller/dockitemmanager.h" + +#include +#include +#include + +#include + +static QGSettings *GSettingsByMenu() +{ + static QGSettings settings("com.deepin.dde.dock.module.menu"); + return &settings; +} + +static QGSettings *GSettingsByTrash() +{ + static QGSettings settings("com.deepin.dde.dock.module.trash"); + return &settings; +} + +MenuWorker::MenuWorker(DBusDock *dockInter,QWidget *parent) + : QObject (parent) + , m_itemManager(DockItemManager::instance(this)) + , m_dockInter(dockInter) + , m_settingsMenu(new QMenu) + , m_fashionModeAct(new QAction(tr("Fashion Mode"), this)) + , m_efficientModeAct(new QAction(tr("Efficient Mode"), this)) + , m_topPosAct(new QAction(tr("Top"), this)) + , m_bottomPosAct(new QAction(tr("Bottom"), this)) + , m_leftPosAct(new QAction(tr("Left"), this)) + , m_rightPosAct(new QAction(tr("Right"), this)) + , m_keepShownAct(new QAction(tr("Keep Shown"), this)) + , m_keepHiddenAct(new QAction(tr("Keep Hidden"), this)) + , m_smartHideAct(new QAction(tr("Smart Hide"), this)) + , m_menuEnable(true) + , m_autoHide(true) + , m_trashPluginShow(true) + , m_opacity(0.4) +{ + initMember(); + initUI(); + initConnection(); + + QTimer::singleShot(0, this, [=] {onGSettingsChanged("enable");}); +} + +MenuWorker::~MenuWorker() +{ + delete m_settingsMenu; +} + +void MenuWorker::initMember() +{ + m_settingsMenu->setAccessibleName("settingsmenu"); + + m_fashionModeAct->setCheckable(true); + m_efficientModeAct->setCheckable(true); + m_topPosAct->setCheckable(true); + m_bottomPosAct->setCheckable(true); + m_leftPosAct->setCheckable(true); + m_rightPosAct->setCheckable(true); + m_keepShownAct->setCheckable(true); + m_keepHiddenAct->setCheckable(true); + m_smartHideAct->setCheckable(true); +} + +void MenuWorker::initUI() +{ + QMenu *modeSubMenu = new QMenu(m_settingsMenu); + modeSubMenu->setAccessibleName("modesubmenu"); + modeSubMenu->addAction(m_fashionModeAct); + modeSubMenu->addAction(m_efficientModeAct); + QAction *modeSubMenuAct = new QAction(tr("Mode"), this); + modeSubMenuAct->setMenu(modeSubMenu); + + QMenu *locationSubMenu = new QMenu(m_settingsMenu); + locationSubMenu->setAccessibleName("locationsubmenu"); + locationSubMenu->addAction(m_topPosAct); + locationSubMenu->addAction(m_bottomPosAct); + locationSubMenu->addAction(m_leftPosAct); + locationSubMenu->addAction(m_rightPosAct); + QAction *locationSubMenuAct = new QAction(tr("Location"), this); + locationSubMenuAct->setMenu(locationSubMenu); + + QMenu *statusSubMenu = new QMenu(m_settingsMenu); + statusSubMenu->setAccessibleName("statussubmenu"); + statusSubMenu->addAction(m_keepShownAct); + statusSubMenu->addAction(m_keepHiddenAct); + statusSubMenu->addAction(m_smartHideAct); + QAction *statusSubMenuAct = new QAction(tr("Status"), this); + statusSubMenuAct->setMenu(statusSubMenu); + + m_hideSubMenu = new QMenu(m_settingsMenu); + m_hideSubMenu->setAccessibleName("pluginsmenu"); + QAction *hideSubMenuAct = new QAction(tr("Plugins"), this); + hideSubMenuAct->setMenu(m_hideSubMenu); + + m_settingsMenu->addAction(modeSubMenuAct); + m_settingsMenu->addAction(locationSubMenuAct); + m_settingsMenu->addAction(statusSubMenuAct); + m_settingsMenu->addAction(hideSubMenuAct); + m_settingsMenu->setTitle("Settings Menu"); +} + +void MenuWorker::initConnection() +{ + connect(m_settingsMenu, &QMenu::triggered, this, &MenuWorker::menuActionClicked); + + connect(GSettingsByMenu(), &QGSettings::changed, this, &MenuWorker::onGSettingsChanged); + connect(GSettingsByTrash(), &QGSettings::changed, this, &MenuWorker::onTrashGSettingsChanged); + + connect(m_itemManager, &DockItemManager::trayVisableCountChanged, this, &MenuWorker::trayVisableCountChanged, Qt::QueuedConnection); + + DApplication *app = qobject_cast(qApp); + if (app) { + connect(app, &DApplication::iconThemeChanged, this, &MenuWorker::gtkIconThemeChanged); + } +} + +void MenuWorker::showDockSettingsMenu() +{ + QTimer::singleShot(0, this, [=] { + onGSettingsChanged("enable"); + }); + + setAutoHide(false); + + bool hasComposite = DWindowManagerHelper::instance()->hasComposite(); + + // create actions + QList actions; + for (auto *p : m_itemManager->pluginList()) { + if (!p->pluginIsAllowDisable()) + continue; + + const bool enable = !p->pluginIsDisable(); + const QString &name = p->pluginName(); + const QString &display = p->pluginDisplayName(); + + if (!m_trashPluginShow && name == "trash") { + continue; + } + + if (name == "multitasking" && !hasComposite) { + continue; + } + + QAction *act = new QAction(display, this); + act->setCheckable(true); + act->setChecked(enable); + act->setData(name); + + actions << act; + } + + // sort by name + std::sort(actions.begin(), actions.end(), [](QAction * a, QAction * b) -> bool { + return a->data().toString() > b->data().toString(); + }); + + // add actions + qDeleteAll(m_hideSubMenu->actions()); + for (auto act : actions) + m_hideSubMenu->addAction(act); + + const DisplayMode displayMode = static_cast(m_dockInter->displayMode()); + const Position position = static_cast(m_dockInter->position()); + const HideMode hideMode = static_cast(m_dockInter->hideMode()); + + m_fashionModeAct->setChecked(displayMode == Fashion); + m_efficientModeAct->setChecked(displayMode == Efficient); + m_topPosAct->setChecked(position == Top); + m_bottomPosAct->setChecked(position == Bottom); + m_leftPosAct->setChecked(position == Left); + m_rightPosAct->setChecked(position == Right); + m_keepShownAct->setChecked(hideMode == KeepShowing); + m_keepHiddenAct->setChecked(hideMode == KeepHidden); + m_smartHideAct->setChecked(hideMode == SmartHide); + + m_settingsMenu->exec(QCursor::pos()); + + setAutoHide(true); +} + +void MenuWorker::onGSettingsChanged(const QString &key) +{ + if (key != "enable") { + return; + } + + QGSettings *setting = GSettingsByMenu(); + + if (setting->keys().contains("enable")) { + const bool isEnable = GSettingsByMenu()->keys().contains("enable") && GSettingsByMenu()->get("enable").toBool(); + m_menuEnable=isEnable && setting->get("enable").toBool(); + } +} + +void MenuWorker::onTrashGSettingsChanged(const QString &key) +{ + if (key != "enable") { + return ; + } + + QGSettings *setting = GSettingsByTrash(); + + if (setting->keys().contains("enable")) { + m_trashPluginShow = GSettingsByTrash()->keys().contains("enable") && GSettingsByTrash()->get("enable").toBool(); + } +} + +void MenuWorker::menuActionClicked(QAction *action) +{ + Q_ASSERT(action); + + if (action == m_fashionModeAct) + return m_dockInter->setDisplayMode(DisplayMode::Fashion); + if (action == m_efficientModeAct) + return m_dockInter->setDisplayMode(Efficient); + + if (action == m_topPosAct) + return m_dockInter->setPosition(Top); + if (action == m_bottomPosAct) + return m_dockInter->setPosition(Bottom); + if (action == m_leftPosAct) + return m_dockInter->setPosition(Left); + if (action == m_rightPosAct) + return m_dockInter->setPosition(Right); + + if (action == m_keepShownAct) + return m_dockInter->setHideMode(KeepShowing); + if (action == m_keepHiddenAct) + return m_dockInter->setHideMode(KeepHidden); + if (action == m_smartHideAct) + return m_dockInter->setHideMode(SmartHide); + + // check plugin hide menu. + const QString &data = action->data().toString(); + if (data.isEmpty()) + return; + for (auto *p : m_itemManager->pluginList()) { + if (p->pluginName() == data) + return p->pluginStateSwitched(); + } +} + +void MenuWorker::trayVisableCountChanged(const int &count) +{ + Q_UNUSED(count); + + emit trayCountChanged(); +} + +void MenuWorker::gtkIconThemeChanged() +{ + m_itemManager->refershItemsIcon(); +} + +void MenuWorker::setAutoHide(const bool autoHide) +{ + if (m_autoHide == autoHide) + return; + + m_autoHide = autoHide; + emit autoHideChanged(m_autoHide); +} diff --git a/frame/util/menuworker.h b/frame/util/menuworker.h new file mode 100644 index 000000000..2010c03e8 --- /dev/null +++ b/frame/util/menuworker.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2018 ~ 2028 Deepin 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 MENUWORKER_H +#define MENUWORKER_H +#include + +#include "constants.h" + +#include + +using DBusDock = com::deepin::dde::daemon::Dock; +class QMenu; +class QAction; +class DockItemManager; +/** + * @brief The MenuWorker class 此类用于处理任务栏右键菜单的逻辑 + */ +class MenuWorker : public QObject +{ + Q_OBJECT +public: + explicit MenuWorker(DBusDock *dockInter,QWidget *parent = nullptr); + ~ MenuWorker(); + + void initMember(); + void initUI(); + void initConnection(); + + void showDockSettingsMenu(); + + inline bool menuEnable() const { return m_menuEnable; } + inline quint8 Opacity() const { return quint8(m_opacity * 255); } + + void onGSettingsChanged(const QString &key); + // TODO 是否还有其他的插件未处理其gsettings配置,这里只是移植之前的代码 + void onTrashGSettingsChanged(const QString &key); + +signals: + void autoHideChanged(const bool autoHide) const; + void trayCountChanged(); + +private slots: + void menuActionClicked(QAction *action); + void trayVisableCountChanged(const int &count); + void gtkIconThemeChanged(); + +public slots: + void setAutoHide(const bool autoHide); + +private: + DockItemManager *m_itemManager; + DBusDock *m_dockInter; + + QMenu *m_settingsMenu; + QMenu *m_hideSubMenu; + QAction *m_fashionModeAct; + QAction *m_efficientModeAct; + QAction *m_topPosAct; + QAction *m_bottomPosAct; + QAction *m_leftPosAct; + QAction *m_rightPosAct; + QAction *m_keepShownAct; + QAction *m_keepHiddenAct; + QAction *m_smartHideAct; + + bool m_menuEnable; + bool m_autoHide; + bool m_trashPluginShow; + double m_opacity; +}; + +#endif // MENUWORKER_H diff --git a/frame/util/monitor.cpp b/frame/util/monitor.cpp index 5b83d3b5b..e7f41ba1b 100644 --- a/frame/util/monitor.cpp +++ b/frame/util/monitor.cpp @@ -25,19 +25,12 @@ #include "monitor.h" -const double DoubleZero = 0.000001; - Monitor::Monitor(QObject *parent) : QObject(parent) , m_x(0) , m_y(0) , m_w(0) , m_h(0) - , m_mmWidth(0) - , m_mmHeight(0) - , m_scale(-1.0) - , m_rotate(0) -// , m_brightness(1.0) , m_enable(false) { @@ -50,7 +43,6 @@ void Monitor::setX(const int x) m_x = x; - Q_EMIT xChanged(m_x); Q_EMIT geometryChanged(); } @@ -61,7 +53,6 @@ void Monitor::setY(const int y) m_y = y; - Q_EMIT yChanged(m_y); Q_EMIT geometryChanged(); } @@ -72,7 +63,6 @@ void Monitor::setW(const int w) m_w = w; - Q_EMIT wChanged(m_w); Q_EMIT geometryChanged(); } @@ -83,57 +73,12 @@ void Monitor::setH(const int h) 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) { + qDebug() << "screen name change from :" << m_name << " to: " << name; m_name = name; } @@ -142,21 +87,6 @@ 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(); @@ -173,22 +103,6 @@ bool compareResolution(const Resolution &first, const Resolution &second) } -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) @@ -197,37 +111,3 @@ void Monitor::setMonitorEnable(bool enable) 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 index f6acfac1d..7309efa32 100644 --- a/frame/util/monitor.h +++ b/frame/util/monitor.h @@ -25,13 +25,15 @@ #ifndef MONITOR_H #define MONITOR_H +#include "constants.h" #include +#include #include using MonitorInter = com::deepin::daemon::display::Monitor; - +using namespace Dock; class Monitor : public QObject { Q_OBJECT @@ -42,12 +44,37 @@ public: bool topDock = true; bool rightDock = true; bool bottomDock = true; - DockPosition(bool l = true, bool t = true, bool r = true, bool b = true) { + DockPosition(bool l = true, bool t = true, bool r = true, bool b = true) + { + qDebug() << leftDock << topDock << rightDock << bottomDock; leftDock = l; topDock = t; rightDock = r; bottomDock = b; } + + bool docked(const Position &pos) + { + switch (pos) { + case Position::Top: + return topDock; + case Position::Bottom: + return bottomDock; + case Position::Left: + return leftDock; + case Position::Right: + return rightDock; + } + Q_UNREACHABLE(); + } + + void reset() + { + leftDock = true; + topDock = true; + rightDock = true; + bottomDock = true; + } }; public: @@ -65,57 +92,26 @@ public: 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: @@ -123,20 +119,10 @@ private: 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; }; diff --git a/frame/util/multiscreenworker.cpp b/frame/util/multiscreenworker.cpp new file mode 100644 index 000000000..44b903c11 --- /dev/null +++ b/frame/util/multiscreenworker.cpp @@ -0,0 +1,1417 @@ +/* + * Copyright (C) 2018 ~ 2028 Deepin 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 "multiscreenworker.h" +#include "window/mainwindow.h" + +#include +#include +#include +#include +#include +#include + +#include + +// 保证以下数据更新顺序(大环节顺序不要变,内部还有一些小的调整,比如任务栏显示区域更新的时候,里面内容的布局方向可能也要更新...) +// Monitor数据->屏幕是否可停靠更新->监视唤醒区域更新,任务栏显示区域更新->拖拽区域更新->通知后端接口,通知窗管 + +MultiScreenWorker::MultiScreenWorker(QWidget *parent, DWindowManagerHelper *helper) + : QObject(nullptr) + , m_parent(parent) + , m_wmHelper(helper) + , m_xcbMisc(XcbMisc::instance()) + , m_eventInter(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_showAni(new QVariantAnimation(this)) + , m_hideAni(new QVariantAnimation(this)) + , m_ds(m_displayInter->primary()) + , m_opacity(0.4) + , m_position(Dock::Position(m_dockInter->position())) + , m_hideMode(Dock::HideMode(m_dockInter->hideMode())) + , m_hideState(Dock::HideState(m_dockInter->hideState())) + , m_displayMode(Dock::DisplayMode(m_dockInter->displayMode())) + , m_screenRawHeight(m_displayInter->screenHeight()) + , m_screenRawWidth(m_displayInter->screenWidth()) + , m_aniStart(false) + , m_draging(false) + , m_autoHide(true) + , m_btnPress(false) +{ + qDebug() << "init dock screen: " << m_ds.current(); + initMembers(); + initConnection(); + initUI(); +} + +MultiScreenWorker::~MultiScreenWorker() +{ + delete m_xcbMisc; +} + +void MultiScreenWorker::initShow() +{ + // 仅在初始化时调用一次 + static bool first = true; + if (!first) + qFatal("this method can only be called once"); + first = false; + + // 这里是为了在调用时让MainWindow更新界面布局方向 + emit requestUpdateLayout(m_ds.current()); + + if (m_hideMode == HideMode::KeepShowing) + showAni(m_ds.current()); + else if (m_hideMode == HideMode::KeepHidden) { + QRect rect = getDockShowGeometry(m_ds.current(), m_position, m_displayMode); + parent()->panel()->setFixedSize(rect.size()); + parent()->panel()->move(0, 0); + + rect = getDockHideGeometry(m_ds.current(), m_position, m_displayMode); + parent()->setFixedSize(rect.size()); + parent()->setGeometry(rect); + } else if (m_hideMode == HideMode::SmartHide) { + if (m_hideState == HideState::Show) + showAni(m_ds.current()); + else if (m_hideState == HideState::Hide) + hideAni(m_ds.current()); + } +} + +QRect MultiScreenWorker::dockRect(const QString &screenName, const Position &pos, const HideMode &hideMode, const DisplayMode &displayMode) +{ + if (hideMode == HideMode::KeepShowing) + return getDockShowGeometry(screenName, pos, displayMode); + else + return getDockHideGeometry(screenName, pos, displayMode); +} + +QRect MultiScreenWorker::dockRect(const QString &screenName) +{ + return dockRect(screenName, m_position, m_hideMode, m_displayMode); +} + +void MultiScreenWorker::handleLeaveEvent(QEvent *event) +{ + Q_UNUSED(event); + + if (m_hideMode == HideMode::KeepShowing) + return; + + if (!m_autoHide) + return; + + // 判断是否还在'离开'监控区域内,是的话不处理,否则按照显示状态来处理 + if (!contains(m_monitorRectList, scaledPos(QCursor::pos()))) { + switch (m_hideMode) { + case HideMode::SmartHide: { + if (m_hideState == HideState::Show) { + showAni(m_ds.current()); + } else { + hideAni(m_ds.current()); + } + } + break; + case HideMode::KeepHidden: + hideAni(m_ds.current()); + break; + default: + return; + } + } +} + +void MultiScreenWorker::onAutoHideChanged(bool autoHide) +{ + m_autoHide = autoHide; + + if (m_autoHide) { + switch (m_hideMode) { + case HideMode::KeepHidden: { + // 这时候鼠标如果在任务栏上,就不能隐藏 + if (!parent()->geometry().contains(QCursor::pos())) + hideAni(m_ds.current()); + } + break; + case HideMode::SmartHide: { + if (m_hideState == HideState::Show) { + showAni(m_ds.current()); + } else if (m_hideState == HideState::Hide) { + hideAni(m_ds.current()); + } + } + break; + case HideMode::KeepShowing: + showAni(m_ds.current()); + break; + } + } +} + +void MultiScreenWorker::updateDaemonDockSize(int dockSize) +{ + m_dockInter->setWindowSize(uint(dockSize)); + if (m_displayMode == DisplayMode::Fashion) + m_dockInter->setWindowSizeFashion(uint(dockSize)); + else + 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(); + // 参数固定长度 + if (3 != arguments.count()) + return; + // 返回的数据中,这一部分对应的是数据发送方的interfacename,可判断是否是自己需要的服务 + QString interfaceName = msg.arguments().at(0).toString(); + if (interfaceName != "com.deepin.dde.daemon.Dock") + return; + QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); + QStringList keys = changedProps.keys(); + foreach (const QString &prop, keys) { + if (prop == "Position") { + onPositionChanged(); + } else if (prop == "DisplayMode") { + onDisplayModeChanged(); + } else if (prop == "HideMode") { + onHideModeChanged(); + } else if (prop == "HideState") { + onHideStateChanged(); + } + } +} + +void MultiScreenWorker::onRegionMonitorChanged(int x, int y, const QString &key) +{ + if (m_registerKey != key) + return; + + // 鼠标按下状态不响应唤醒 + if (m_btnPress) + return; + + if (m_draging || m_aniStart) { + qDebug() << "dock is draging or animation is running"; + return; + } + + QString toScreen; + QScreen *screen = Utils::screenAtByScaled(QPoint(x, y)); + if (!screen) { + qDebug() << "cannot find the screen" << QPoint(x, y); + return; + } + + toScreen = screen->name(); + + /** + * 坐标位于当前屏幕边缘时,当做屏幕内移动处理(防止鼠标移动到边缘时不唤醒任务栏) + * 使用screenAtByScaled获取屏幕名时,实际上获取的不一定是当前屏幕 + * 举例:点(100,100)不在(0,0,100,100)的屏幕上 + */ + if (onScreenEdge(m_ds.current(), QPoint(x, y))) { + toScreen = m_ds.current(); + } + + // 过滤重复坐标 + static QPoint lastPos(0, 0); + if (lastPos == QPoint(x, y)) { +#ifdef QT_DEBUG + qDebug() << "same point,should return"; +#endif + return; + } + lastPos = QPoint(x, y); + +#ifdef QT_DEBUG + qDebug() << x << y << m_ds.current() << toScreen; +#endif + + // 任务栏显示状态,但需要切换屏幕 + if (toScreen != m_ds.current()) { + // 移动Dock至相应屏相应位置 + if (m_launcherInter->IsVisible())//启动器显示,则dock不显示 + return; + + // 复制模式.不需要响应切换屏幕 + QList monitorList = validMonitorList(m_monitorInfo); + if (monitorList.size() == 2 && monitorList.first()->rect() == monitorList.last()->rect()) { +#ifdef QT_DEBUG + qDebug() << "copy mode or merge mode"; +#endif + parent()->setFixedSize(dockRect(m_ds.current()).size()); + parent()->setGeometry(dockRect(m_ds.current())); + return; + } + + m_ds.updateDockedScreen(screen->name()); + + Monitor *currentMonitor = monitorByName(validMonitorList(m_monitorInfo), toScreen); + if (!currentMonitor) { +#ifdef QT_DEBUG + qDebug() << "cannot find monitor by name: " << toScreen; +#endif + return; + } + + // 检查边缘是否允许停靠 + if (currentMonitor->dockPosition().docked(m_position)) { + if (hideMode() == HideMode::KeepHidden || hideMode() == HideMode::SmartHide) { + showAni(m_ds.current()); + } else if (hideMode() == HideMode::KeepShowing) { + changeDockPosition(m_ds.last(), m_ds.current(), m_position, m_position); + } + } + } else { + // 任务栏隐藏状态,但需要显示 + if (hideMode() == HideMode::KeepShowing) { +#ifdef QT_DEBUG + qDebug() << "showing"; +#endif + parent()->setFixedSize(dockRect(m_ds.current()).size()); + parent()->setGeometry(dockRect(m_ds.current())); + return; + } + + if (m_showAni->state() == QVariantAnimation::Running) { +#ifdef QT_DEBUG + qDebug() << "animation is running"; +#endif + return; + } + + const QRect boundRect = parent()->visibleRegion().boundingRect(); +#ifdef QT_DEBUG + qDebug() << "boundRect:" << boundRect; +#endif + if ((hideMode() == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) + && (boundRect.size().isEmpty())) { + showAni(m_ds.current()); + } + } +} + +void MultiScreenWorker::onMonitorListChanged(const QList &mons) +{ + if (mons.isEmpty()) + return; + + QList ops; + for (const auto *mon : m_monitorInfo.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); + + // 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()); + + m_monitorInfo.insert(mon, inter); + + inter->setSync(false); +} + +void MultiScreenWorker::monitorRemoved(const QString &path) +{ + Monitor *monitor = nullptr; + for (auto it(m_monitorInfo.cbegin()); it != m_monitorInfo.cend(); ++it) { + if (it.key()->path() == path) { + monitor = it.key(); + break; + } + } + if (!monitor) + return; + + m_monitorInfo.value(monitor)->deleteLater(); + m_monitorInfo.remove(monitor); + + monitor->deleteLater(); +} + +void MultiScreenWorker::showAniFinished() +{ + const QRect rect = dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode); + + parent()->panel()->setFixedSize(rect.size()); + parent()->panel()->move(0, 0); + + emit requestUpdateFrontendGeometry(rect); + emit requestNotifyWindowManager(); + emit requestUpdateDragArea(); +} + +void MultiScreenWorker::hideAniFinished() +{ + const QRect rect = dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode); + + parent()->panel()->setFixedSize(rect.size()); + parent()->panel()->move(0, 0); + + emit requestUpdateFrontendGeometry(rect); + emit requestNotifyWindowManager(); +} + +void MultiScreenWorker::onWindowSizeChanged(uint value) +{ + Q_UNUSED(value); + + m_monitorUpdateTimer->start(); +} + +void MultiScreenWorker::primaryScreenChanged() +{ + const int screenRawHeight = m_displayInter->screenHeight(); + const int screenRawWidth = m_displayInter->screenWidth(); + + // 无效值 + if (screenRawHeight == 0 || screenRawWidth == 0) { + return; + } + + m_monitorUpdateTimer->start(); +} + +void MultiScreenWorker::onPositionChanged() +{ + const Position position = Dock::Position(m_dockInter->position()); + Position lastPos = m_position; + if (lastPos == position) + return; +#ifdef QT_DEBUG + qDebug() << "position change from: " << lastPos << " to: " << position; +#endif + m_position = position; + + // 更新鼠标拖拽样式,在类内部设置到qApp单例上去 + if ((Top == m_position) || (Bottom == m_position)) { + parent()->panel()->setCursor(Qt::SizeVerCursor); + } else { + parent()->panel()->setCursor(Qt::SizeHorCursor); + } + + DockItem::setDockPosition(position); + qApp->setProperty(PROP_POSITION, QVariant::fromValue(position)); + + emit requestUpdatePosition(lastPos, position); + emit requestUpdateRegionMonitor(); +} + +void MultiScreenWorker::onDisplayModeChanged() +{ + DisplayMode displayMode = Dock::DisplayMode(m_dockInter->displayMode()); + + if (displayMode == m_displayMode) + return; + + qDebug() << "display mode change:" << displayMode; + + m_displayMode = displayMode; + + DockItem::setDockDisplayMode(displayMode); + qApp->setProperty(PROP_DISPLAY_MODE, QVariant::fromValue(displayMode)); + + parent()->setFixedSize(dockRect(m_ds.current()).size()); + parent()->move(dockRect(m_ds.current()).topLeft()); + + emit displayModeChanegd(); + emit requestUpdateRegionMonitor(); + emit requestUpdateFrontendGeometry(dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode)); + emit requestNotifyWindowManager(); +} + +void MultiScreenWorker::onHideModeChanged() +{ + HideMode hideMode = Dock::HideMode(m_dockInter->hideMode()); + + if (m_hideMode == hideMode) + return; + + qDebug() << "hidemode change:" << hideMode; + + m_hideMode = hideMode; + + emit requestUpdateFrontendGeometry(dockRect(m_ds.current())); + emit requestNotifyWindowManager(); +} + +void MultiScreenWorker::onHideStateChanged() +{ + const Dock::HideState state = Dock::HideState(m_dockInter->hideState()); + + if (state == Dock::Unknown) + return; + + qDebug() << "hidestate change:" << state; + + m_hideState = state; + + // 两种隐藏模式下都可以被唤醒 + if (m_hideMode == HideMode::SmartHide || m_hideMode == HideMode::KeepHidden) { + if (m_hideState == HideState::Show) + showAni(m_ds.current()); + else if (m_hideState == HideState::Hide) + hideAni(m_ds.current()); + } else if (m_hideMode == HideMode::KeepShowing) { + showAni(m_ds.current()); + } +} + +void MultiScreenWorker::onOpacityChanged(const double value) +{ + if (int(m_opacity * 100) == int(value * 100)) return; + + m_opacity = value; + + emit opacityChanged(quint8(value * 255)); +} + +void MultiScreenWorker::onRequestUpdateRegionMonitor() +{ + if (!m_registerKey.isEmpty()) { +#ifdef QT_DEBUG + bool ret = m_eventInter->UnregisterArea(m_registerKey); + qDebug() << "取消唤起区域监听:" << ret; +#else + m_eventInter->UnregisterArea(m_registerKey); +#endif + m_registerKey.clear(); + } + + const static int flags = Motion | Button | Key; + const static int monitorHeight = 15; + + // 任务栏唤起区域 + m_monitorRectList.clear(); + foreach (Monitor *inter, validMonitorList(m_monitorInfo)) { + // 屏幕不可用或此位置不可停靠时,不用监听这块区域 + if (!inter->enable() || !inter->dockPosition().docked(m_position)) + continue; + + 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; + } + 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(); + } + break; + case Left: { + rect.x1 = inter->x(); + rect.y1 = inter->y(); + rect.x2 = inter->x() + monitorHeight; + rect.y2 = inter->y() + inter->h(); + } + 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(); + } + break; + } + + if (!m_monitorRectList.contains(rect)) { + m_monitorRectList << rect; +#ifdef QT_DEBUG + qDebug() << "监听区域:" << rect.x1 << rect.y1 << rect.x2 << rect.y2; +#endif + } + } + + m_registerKey = m_eventInter->RegisterAreas(m_monitorRectList, flags); +} + +void MultiScreenWorker::onRequestUpdateFrontendGeometry(const QRect &rect) +{ + const qreal scale = scaleByName(m_ds.current()); +#ifdef QT_DEBUG + qDebug() << rect; +#endif + m_dockInter->SetFrontendWindowRect(int(rect.x() / scale), int(rect.y() / scale), uint(rect.width() / scale), uint(rect.height() / scale)); +} + +void MultiScreenWorker::onRequestNotifyWindowManager() +{ + // 先清除原先的窗管任务栏区域 + m_xcbMisc->clear_strut_partial(xcb_window_t(parent()->winId())); + + if (m_hideMode != Dock::KeepShowing) + return; + + const auto ratio = parent()->devicePixelRatioF(); + + const QRect rect = getDockShowGeometry(m_ds.current(), m_position, m_displayMode); + qDebug() << "wm dock area:" << rect; + const QPoint &p = rawXPosition(rect.topLeft()); + + XcbMisc::Orientation orientation = XcbMisc::OrientationTop; + uint strut = 0; + uint strutStart = 0; + uint strutEnd = 0; + + switch (m_position) { + case Position::Top: + orientation = XcbMisc::OrientationTop; + strut = p.y() + rect.height() * ratio; + strutStart = p.x(); + strutEnd = qMin(qRound(p.x() + rect.width() * ratio), rect.right()); + break; + case Position::Bottom: + orientation = XcbMisc::OrientationBottom; + strut = m_screenRawHeight - p.y(); + strutStart = p.x(); + strutEnd = qMin(qRound(p.x() + rect.width() * ratio), rect.right()); + break; + case Position::Left: + orientation = XcbMisc::OrientationLeft; + strut = p.x() + rect.width() * ratio; + strutStart = p.y(); + strutEnd = qMin(qRound(p.y() + rect.height() * ratio), rect.bottom()); + break; + case Position::Right: + orientation = XcbMisc::OrientationRight; + strut = m_screenRawWidth - p.x(); + strutStart = p.y(); + strutEnd = qMin(qRound(p.y() + rect.height() * ratio), rect.bottom()); + break; + } + +#ifdef QT_DEBUG + qDebug() << strut << strutStart << strutEnd; +#endif + m_xcbMisc->set_strut_partial(parent()->winId(), orientation, strut + WINDOWMARGIN * ratio, strutStart, strutEnd); +} + +void MultiScreenWorker::onRequestUpdatePosition(const Position &fromPos, const Position &toPos) +{ + qDebug() << "request change pos from: " << fromPos << " to: " << toPos; + // 更新要切换到的屏幕 + m_ds.updateDockedScreen(getValidScreen(m_position)); + + qDebug() << "update allow screen: " << m_ds.current(); + + // 无论什么模式,都先显示 + changeDockPosition(m_ds.last(), m_ds.current(), fromPos, toPos); +} + +void MultiScreenWorker::onRequestUpdateDragArea() +{ + parent()->resetDragWindow(); +} + +void MultiScreenWorker::onRequestUpdateMonitorInfo() +{ +#ifdef QT_DEBUG + foreach (auto monitor, m_monitorInfo.keys()) { + qDebug() << monitor->name() << monitor->enable(); + } +#endif + // 双屏,复制模式,两个屏幕的信息是一样的 + if (validMonitorList(m_monitorInfo).size() == 2 + && validMonitorList(m_monitorInfo).first()->rect() == validMonitorList(m_monitorInfo).last()->rect()) { +#ifdef QT_DEBUG + qDebug() << "repeat screen"; +#endif + return; + } + + m_monitorUpdateTimer->start(); +} + +void MultiScreenWorker::updateMonitorDockedInfo() +{ + QListscreens = validMonitorList(m_monitorInfo); + + if (screens.size() == 1) { + // 只剩下一个可用的屏幕 + screens.first()->dockPosition().reset(); + updateDockScreenName(screens.first()->name()); + return; + } + + // 最多支持双屏,这里只计算双屏,单屏默认四边均可停靠任务栏 + if (screens.size() != 2) { +#ifdef QT_DEBUG + qDebug() << "screen count:" << screens.count(); +#endif + return; + } + + Monitor *s1 = screens.at(0); + Monitor *s2 = screens.at(1); + if (!s1 || !s2) { + qFatal("shouldn't be here"); + } + + qDebug() << "monitor info changed" << s1->rect() << s2->rect(); + + // 先重置 + s1->dockPosition().reset(); + s2->dockPosition().reset(); + + // 对角拼接,重置,默认均可停靠 + if (s1->bottomRight() == s2->topLeft() + || s1->topLeft() == s2->bottomRight()) { +#ifdef QT_DEBUG + qDebug() << "diagonal: " << s1->rect() << s2->rect(); +#endif + return; + } + + // 左右拼接,s1左,s2右 + if (s1->right() == s2->left() + && (s1->topRight() == s2->topLeft() || s1->bottomRight() == s2->bottomLeft())) { +#ifdef QT_DEBUG + qDebug() << "horizontal: " << s1->rect() << s2->rect(); +#endif + s1->dockPosition().rightDock = false; + s2->dockPosition().leftDock = false; + } + // 左右拼接,s1右,s2左 + if (s1->left() == s2->right() + && (s1->topLeft() == s2->topRight() || s1->bottomLeft() == s2->bottomRight())) { +#ifdef QT_DEBUG + qDebug() << "horizontal: " << s1->rect() << s2->rect(); +#endif + s1->dockPosition().leftDock = false; + s2->dockPosition().rightDock = false; + } + + // 上下拼接,s1上,s2下 + if (s1->bottom() == s2->top() + && (s1->bottomLeft() == s2->topLeft() || s1->bottomRight() == s2->topRight())) { +#ifdef QT_DEBUG + qDebug() << "vertical: " << s1->rect() << s2->rect(); +#endif + s1->dockPosition().bottomDock = false; + s2->dockPosition().topDock = false; + } + + // 上下拼接,s1下,s2上 + if (s1->top() == s2->bottom() + && (s1->topLeft() == s2->bottomLeft() || s1->topRight() == s2->bottomRight())) { +#ifdef QT_DEBUG + qDebug() << "vertical: " << s1->rect() << s2->rect(); +#endif + s1->dockPosition().topDock = false; + s2->dockPosition().bottomDock = false; + } +} + +void MultiScreenWorker::initMembers() +{ + DockItem::setDockPosition(m_position); + qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position)); + DockItem::setDockDisplayMode(m_displayMode); + qApp->setProperty(PROP_DISPLAY_MODE, QVariant::fromValue(m_displayMode)); + + m_monitorUpdateTimer->setInterval(10); + m_monitorUpdateTimer->setSingleShot(true); + + // 设置应用角色为任务栏 + m_xcbMisc->set_window_type(xcb_window_t(parent()->winId()), XcbMisc::Dock); + + // 初始化动画信息 + m_showAni->setEasingCurve(QEasingCurve::InOutCubic); + m_hideAni->setEasingCurve(QEasingCurve::InOutCubic); + + const bool composite = m_wmHelper->hasComposite(); + +#ifndef DISABLE_SHOW_ANIMATION + const int duration = composite ? ANIMATIONTIME : 0; +#else + const int duration = 0; +#endif + + m_showAni->setDuration(duration); + m_hideAni->setDuration(duration); + + //1\初始化monitor信息 + onMonitorListChanged(m_displayInter->monitors()); + + //2\初始化屏幕停靠信息 + updateMonitorDockedInfo(); + + //3\初始化监视区域 + onRequestUpdateRegionMonitor(); + + //4\初始化任务栏停靠屏幕 + autosetDockScreen(); +} + +void MultiScreenWorker::initConnection() +{ + auto updateGeometry = [ = ](QVariant value){ + QRect rect = value.toRect(); + parent()->setFixedSize(rect.size()); + parent()->setGeometry(rect); + + switch (m_position) { + case Position::Top: { + const int panelSize = parent()->panel()->height(); + parent()->panel()->move(0, rect.height() - panelSize); + } + break; + case Position::Left: { + const int panelSize = parent()->panel()->width(); + parent()->panel()->move(rect.width() - panelSize, 0); + } + break; + case Position::Bottom: + case Position::Right: + break; + } + }; + + connect(m_showAni, &QVariantAnimation::valueChanged, this, [ = ](QVariant value){updateGeometry(value);}); + connect(m_hideAni, &QVariantAnimation::valueChanged, this, [ = ](QVariant value){updateGeometry(value);}); + + connect(m_showAni, &QVariantAnimation::finished, this, &MultiScreenWorker::showAniFinished); + connect(m_hideAni, &QVariantAnimation::finished, this, &MultiScreenWorker::hideAniFinished); + + //FIX: 这里关联信号有时候收不到,未查明原因,handleDbusSignal处理 +#if 0 + // connect(m_dockInter, &DBusDock::PositionChanged, this, &MultiScreenWorker::onPositionChanged); + // connect(m_dockInter, &DBusDock::DisplayModeChanged, this, &MultiScreenWorker::onDisplayModeChanged); + // connect(m_dockInter, &DBusDock::HideModeChanged, this, &MultiScreenWorker::hideModeChanged); + // connect(m_dockInter, &DBusDock::HideStateChanged, this, &MultiScreenWorker::hideStateChanged); +#else + QDBusConnection::sessionBus().connect("com.deepin.dde.daemon.Dock", + "/com/deepin/dde/daemon/Dock", + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + "sa{sv}as", + this, SLOT(handleDbusSignal(QDBusMessage))); +#endif + connect(m_dockInter, &DBusDock::ServiceRestarted, this, [ = ] { + autosetDockScreen(); + emit requestUpdateFrontendGeometry(dockRect(m_ds.current())); + }); + connect(m_dockInter, &DBusDock::OpacityChanged, this, &MultiScreenWorker::onOpacityChanged); + connect(m_dockInter, &DBusDock::WindowSizeEfficientChanged, this, &MultiScreenWorker::onWindowSizeChanged); + connect(m_dockInter, &DBusDock::WindowSizeFashionChanged, this, &MultiScreenWorker::onWindowSizeChanged); + + connect(m_displayInter, &DisplayInter::ScreenWidthChanged, this, [ = ](ushort value) {m_screenRawWidth = value;}); + connect(m_displayInter, &DisplayInter::ScreenHeightChanged, this, [ = ](ushort value) {m_screenRawHeight = value;}); + connect(m_displayInter, &DisplayInter::MonitorsChanged, this, &MultiScreenWorker::onMonitorListChanged); + connect(m_displayInter, &DisplayInter::MonitorsChanged, this, &MultiScreenWorker::requestUpdateRegionMonitor); + + connect(m_displayInter, &DisplayInter::PrimaryRectChanged, this, &MultiScreenWorker::primaryScreenChanged, Qt::QueuedConnection); + connect(m_displayInter, &DisplayInter::ScreenHeightChanged, this, &MultiScreenWorker::primaryScreenChanged, Qt::QueuedConnection); + connect(m_displayInter, &DisplayInter::ScreenWidthChanged, this, &MultiScreenWorker::primaryScreenChanged, Qt::QueuedConnection); + connect(m_displayInter, &DisplayInter::PrimaryChanged, this, &MultiScreenWorker::primaryScreenChanged, Qt::QueuedConnection); + connect(m_displayInter, &DisplayInter::PrimaryChanged, this, [ = ] { + m_ds.updatePrimary(m_displayInter->primary()); + }); + + connect(m_eventInter, &XEventMonitor::CursorMove, this, &MultiScreenWorker::onRegionMonitorChanged); + connect(m_eventInter, &XEventMonitor::ButtonPress, this, [=]{m_btnPress = true;}); + connect(m_eventInter, &XEventMonitor::ButtonRelease, this, [=]{m_btnPress = false;}); + + 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); + connect(this, &MultiScreenWorker::requestUpdateDragArea, this, &MultiScreenWorker::onRequestUpdateDragArea); + connect(this, &MultiScreenWorker::requestUpdateMonitorInfo, this, &MultiScreenWorker::onRequestUpdateMonitorInfo); + + connect(m_monitorUpdateTimer, &QTimer::timeout, this, [ = ] { + // 更新屏幕停靠信息 + updateMonitorDockedInfo(); + // 更新所在屏幕 + autosetDockScreen(); + // 更新任务栏自身信息 + /** + *注意这里要先对parent()进行setFixedSize,在分辨率切换过程中,setGeometry可能会导致其大小未改变 + */ + parent()->setFixedSize(dockRect(m_ds.current()).size()); + parent()->setGeometry(dockRect(m_ds.current())); + parent()->panel()->setFixedSize(dockRect(m_ds.current()).size()); + parent()->panel()->move(0, 0); + // 通知后端 + emit requestUpdateFrontendGeometry(dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode)); + // 拖拽区域 + emit requestUpdateDragArea(); + // 监控区域 + emit requestUpdateRegionMonitor(); + // 通知窗管 + emit requestNotifyWindowManager(); + }); + + checkDaemonDockService(); +} + +void MultiScreenWorker::initUI() +{ + // 设置界面大小 + parent()->setFixedSize(dockRect(m_ds.current()).size()); + parent()->move(dockRect(m_ds.current()).topLeft()); + parent()->panel()->setFixedSize(dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode).size()); + parent()->panel()->move(0, 0); + + onPositionChanged(); + onDisplayModeChanged(); + onHideModeChanged(); + onHideStateChanged(); + onOpacityChanged(m_dockInter->opacity()); + + // 初始化透明度 + QTimer::singleShot(0, this, [ = ] {onOpacityChanged(m_dockInter->opacity());}); +} + +void MultiScreenWorker::showAni(const QString &screen) +{ + if (m_showAni->state() == QVariantAnimation::Running || m_aniStart) + return; + + emit requestUpdateFrontendGeometry(dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode)); + + /************************************************************************ + * 务必先走第一步,再走第二部,否则就会出现从一直隐藏切换为一直显示,任务栏不显示的问题 + ************************************************************************/ + //1 先停掉其他的动画,否则这里的修改可能会被其他的动画覆盖掉 + if (m_hideAni->state() == QVariantAnimation::Running) + m_hideAni->stop(); + + parent()->panel()->setFixedSize(dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode).size()); + parent()->panel()->move(0, 0); + + //2 任务栏位置已经正确就不需要再重复一次动画了 + if (getDockShowGeometry(screen, m_position, m_displayMode) == parent()->geometry()) { + emit requestNotifyWindowManager(); + return; + } + + m_showAni->setStartValue(getDockHideGeometry(screen, m_position, m_displayMode)); + m_showAni->setEndValue(getDockShowGeometry(screen, m_position, m_displayMode)); + m_showAni->start(); +} + +void MultiScreenWorker::hideAni(const QString &screen) +{ + if (m_hideAni->state() == QVariantAnimation::Running || m_aniStart) + return; + + /************************************************************************ + * 务必先走第一步,再走第二部,否则就会出现从一直隐藏切换为一直显示,任务栏不显示的问题 + ************************************************************************/ + //1 先停掉其他的动画,否则这里的修改可能会被其他的动画覆盖掉 + if (m_showAni->state() == QVariantAnimation::Running) + m_showAni->stop(); + + parent()->panel()->setFixedSize(dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode).size()); + parent()->panel()->move(0, 0); + + //2 任务栏位置已经正确就不需要再重复一次动画了 + if (getDockHideGeometry(screen, static_cast(m_position), m_displayMode) == parent()->geometry()) { + emit requestNotifyWindowManager(); + return; + } + + m_hideAni->setStartValue(getDockShowGeometry(screen, m_position, m_displayMode)); + m_hideAni->setEndValue(getDockHideGeometry(screen, m_position, m_displayMode)); + m_hideAni->start(); +} + +void MultiScreenWorker::changeDockPosition(QString fromScreen, QString toScreen, const Position &fromPos, const Position &toPos) +{ + if (fromScreen == toScreen && fromPos == toPos) { + qDebug() << "shouldn't be here,nothing happend!"; + return; + } + + // 更新屏幕信息 + m_ds.updateDockedScreen(toScreen); + + // TODO: 考虑切换过快的情况,这里需要停止上一次的动画,可增加信息号控制,暂时无需要 + qDebug() << "from: " << fromScreen << " to: " << toScreen; + + QSequentialAnimationGroup *group = new QSequentialAnimationGroup(this); + + QVariantAnimation *ani1 = new QVariantAnimation(group); + QVariantAnimation *ani2 = new QVariantAnimation(group); + + // 初始化动画信息 + ani1->setEasingCurve(QEasingCurve::InOutCubic); + ani2->setEasingCurve(QEasingCurve::InOutCubic); + + const bool composite = m_wmHelper->hasComposite(); +#ifndef DISABLE_SHOW_ANIMATION + const int duration = composite ? ANIMATIONTIME : 0; +#else + const int duration = 0; +#endif + + ani1->setDuration(duration); + ani2->setDuration(duration); + + // 隐藏 + ani1->setStartValue(getDockShowGeometry(fromScreen, fromPos, m_displayMode)); + ani1->setEndValue(getDockHideGeometry(fromScreen, fromPos, m_displayMode)); +#ifdef QT_DEBUG + qDebug() << fromScreen << "hide from :" << getDockShowGeometry(fromScreen, fromPos, m_displayMode); + qDebug() << fromScreen << "hide to :" << getDockHideGeometry(fromScreen, fromPos, m_displayMode); +#endif + + // 显示 + ani2->setStartValue(getDockHideGeometry(toScreen, toPos, m_displayMode)); + ani2->setEndValue(getDockShowGeometry(toScreen, toPos, m_displayMode)); +#ifdef QT_DEBUG + qDebug() << toScreen << "show from :" << getDockHideGeometry(toScreen, toPos, m_displayMode); + qDebug() << toScreen << "show to :" << getDockShowGeometry(toScreen, toPos, m_displayMode); +#endif + + group->addAnimation(ani1); + group->addAnimation(ani2); + + // 隐藏时固定一下内容大小 + connect(ani1, &QVariantAnimation::stateChanged, this, [ = ](QAbstractAnimation::State newState, QAbstractAnimation::State oldState) { + if (newState == QVariantAnimation::Running && oldState == QVariantAnimation::Stopped) { + parent()->panel()->setFixedSize(dockRect(fromScreen, fromPos, HideMode::KeepShowing, m_displayMode).size()); + parent()->panel()->move(0, 0); + } + }); + + auto updateGeometry = [ = ](const QString &screenName, const Position &pos,QVariant value){ + const QRect &rect = value.toRect(); + parent()->setFixedSize(rect.size()); + parent()->setGeometry(rect); + + parent()->panel()->setFixedSize(dockRect(screenName, pos, HideMode::KeepShowing, m_displayMode).size()); + parent()->panel()->move(0, 0); + + switch (m_position) { + case Position::Top: { + const int panelSize = parent()->panel()->height(); + parent()->panel()->move(0, rect.height() - panelSize); + } + break; + case Position::Left: { + const int panelSize = parent()->panel()->width(); + parent()->panel()->move(rect.width() - panelSize, 0); + } + break; + case Position::Bottom: + case Position::Right: + break; + } + }; + + connect(ani1, &QVariantAnimation::valueChanged, this, [ = ](QVariant value) { + updateGeometry(fromScreen, fromPos, value); + }); + + // 显示时固定一下内容大小 + connect(ani2, &QVariantAnimation::stateChanged, this, [ = ](QAbstractAnimation::State newState, QAbstractAnimation::State oldState) { + if (newState == QVariantAnimation::Running && oldState == QVariantAnimation::Stopped) { + parent()->panel()->setFixedSize(dockRect(toScreen, toPos, HideMode::KeepShowing, m_displayMode).size()); + parent()->panel()->move(0, 0); + } + }); + + connect(ani2, &QVariantAnimation::valueChanged, this, [ = ](QVariant value) { + updateGeometry(toScreen, toPos, value); + }); + + // 如果更改了显示位置,在显示之前应该更新一下界面布局方向 + if (fromPos != toPos) + connect(ani1, &QVariantAnimation::finished, this, [ = ] { + // 预设一下大小 + parent()->panel()->setFixedSize(dockRect(m_ds.current(), m_position, HideMode::KeepHidden, m_displayMode).size()); + + // 先清除原先的窗管任务栏区域 + m_xcbMisc->clear_strut_partial(xcb_window_t(parent()->winId())); + + // 隐藏后需要通知界面更新布局方向 + emit requestUpdateLayout(m_ds.current()); + }, Qt::DirectConnection); + + + connect(group, &QVariantAnimation::finished, this, [ = ] { + m_aniStart = false; + + // 结束之后需要根据确定需要再隐藏 + emit showAniFinished(); + emit requestUpdateFrontendGeometry(dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode)); + emit requestNotifyWindowManager(); + }); + + m_aniStart = true; + + group->start(QVariantAnimation::DeleteWhenStopped); +} + +void MultiScreenWorker::updateDockScreenName(const QString &screenName) +{ + Q_UNUSED(screenName); + + m_ds.updateDockedScreen(getValidScreen(m_position)); + + qDebug() << "update dock screen: " << m_ds.current(); + + emit requestUpdateLayout(m_ds.current()); +} + +QString MultiScreenWorker::getValidScreen(const Position &pos) +{ + QList monitorList = validMonitorList(m_monitorInfo); + // 查找主屏 + QString primaryName; + foreach (auto monitor, monitorList) { + primaryName = monitor->name(); + break; + } + + Q_ASSERT(!primaryName.isEmpty()); + + Monitor *primaryMonitor = monitorByName(validMonitorList(m_monitorInfo), primaryName); + + Q_ASSERT(primaryMonitor); + + // 优先选用主屏显示 + if (primaryMonitor->dockPosition().docked(pos)) + return primaryName; + + // 主屏不满足再找其他屏幕 + foreach (auto monitor, monitorList) { + if (monitor->name() != primaryName && monitor->dockPosition().docked(pos)) { + return monitor->name(); + } + } + + Q_UNREACHABLE(); +} + +void MultiScreenWorker::autosetDockScreen() +{ + QList monitorList = validMonitorList(m_monitorInfo); + if (monitorList.size() == 2) { + Monitor *primaryMonitor = monitorByName(validMonitorList(m_monitorInfo), m_ds.primary()); + if (!primaryMonitor->dockPosition().docked(position())) { + foreach (auto monitor, monitorList) { + if (monitor->name() != m_ds.current() + && monitor->dockPosition().docked(position())) { + m_ds.updateDockedScreen(monitor->name()); +#ifdef QT_DEBUG + qDebug() << "update dock screen: " << monitor->name(); +#endif + emit requestUpdateLayout(m_ds.current()); + } + } + } + } +} + +void MultiScreenWorker::checkDaemonDockService() +{ + // com.deepin.dde.daemon.Dock服务比dock晚启动,导致dock启动后的状态错误 + const QString serverName = "com.deepin.dde.daemon.Dock"; + 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()) { + if (m_dockInter) { + delete m_dockInter; + m_dockInter = nullptr; + } + + m_dockInter = new DBusDock(serverName, "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this); + + onPositionChanged(); + onDisplayModeChanged(); + onHideModeChanged(); + onHideStateChanged(); + onOpacityChanged(m_dockInter->opacity()); + + disconnect(ifc); + } + }); + } +} + +MainWindow *MultiScreenWorker::parent() +{ + return static_cast(m_parent); +} + +QRect MultiScreenWorker::getDockShowGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode) +{ + QRect rect; + foreach (Monitor *inter, validMonitorList(m_monitorInfo)) { + if (inter->name() == screenName) { + const int dockSize = int(displaymode == DisplayMode::Fashion ? m_dockInter->windowSizeFashion() : m_dockInter->windowSizeEfficient()); + + switch (static_cast(pos)) { + case Top: { + rect.setX(inter->x() + WINDOWMARGIN); + rect.setY(inter->y() + WINDOWMARGIN); + rect.setWidth(inter->w() - 2 * WINDOWMARGIN); + rect.setHeight(dockSize); + } + break; + case Bottom: { + rect.setX(inter->x() + WINDOWMARGIN); + rect.setY(inter->y() + inter->h() - WINDOWMARGIN - dockSize); + rect.setWidth(inter->w() - 2 * WINDOWMARGIN); + rect.setHeight(dockSize); + } + break; + case Left: { + rect.setX(inter->x() + WINDOWMARGIN); + rect.setY(inter->y() + WINDOWMARGIN); + rect.setWidth(dockSize); + rect.setHeight(inter->h() - 2 * WINDOWMARGIN); + } + break; + case Right: { + rect.setX(inter->x() + inter->w() - WINDOWMARGIN - dockSize); + rect.setY(inter->y() + WINDOWMARGIN); + rect.setWidth(dockSize); + rect.setHeight(inter->h() - 2 * WINDOWMARGIN); + } + } + break; + } + } + +#ifdef QT_DEBUG + qDebug() << rect; +#endif + + return rect; +} + +QRect MultiScreenWorker::getDockHideGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode) +{ + QRect rect; + foreach (Monitor *inter, validMonitorList(m_monitorInfo)) { + if (inter->name() == screenName) { + const int margin = (displaymode == DisplayMode::Fashion ? WINDOWMARGIN : 0); + + switch (static_cast(pos)) { + case Top: { + rect.setX(inter->x() + margin); + rect.setY(inter->y()); + rect.setWidth(inter->w() - 2 * margin); + rect.setHeight(0); + } + break; + case Bottom: { + rect.setX(inter->x() + margin); + rect.setY(inter->y() + inter->h()); + rect.setWidth(inter->w() - 2 * margin); + rect.setHeight(0); + } + break; + case Left: { + rect.setX(inter->x()); + rect.setY(inter->y() + margin); + rect.setWidth(0); + rect.setHeight(inter->h() - 2 * margin); + } + break; + case Right: { + rect.setX(inter->x() + inter->w()); + rect.setY(inter->y() + margin); + rect.setWidth(0); + rect.setHeight(inter->h() - 2 * margin); + } + break; + } + } + } + +#ifdef QT_DEBUG + qDebug() << rect; +#endif + + 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()) { + if (screen->name() == screenName) + return screen; + } + return nullptr; +} + +qreal MultiScreenWorker::scaleByName(const QString &screenName) +{ + foreach (auto screen, qApp->screens()) { + if (screen->name() == screenName) + return screen->devicePixelRatio(); + } + + return qApp->devicePixelRatio();; +} + +bool MultiScreenWorker::onScreenEdge(const QString &screenName, const QPoint &point) +{ + bool ret = false; + QScreen *screen = screenByName(screenName); + if (screen) { + 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; + } + 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) +{ + qDebug() << rect.x1 << rect.y1 << rect.x2 << rect.y2; + 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); + + return screen ? screen->geometry().topLeft() + + (scaledPos - screen->geometry().topLeft()) * + screen->devicePixelRatio() + : scaledPos; +} + +const QPoint MultiScreenWorker::scaledPos(const QPoint &rawXPos) +{ + QScreen const *screen = Utils::screenAt(rawXPos); + + return screen + ? screen->geometry().topLeft() + + (rawXPos - screen->geometry().topLeft()) / screen->devicePixelRatio() + : rawXPos; +} + +QList MultiScreenWorker::validMonitorList(const QMap &map) +{ + QList list; + QMapIteratorit(map); + while (it.hasNext()) { + it.next(); + if (it.key()->enable()) + list << it.key(); + } + return list; +} diff --git a/frame/util/multiscreenworker.h b/frame/util/multiscreenworker.h new file mode 100644 index 000000000..16f3aed2a --- /dev/null +++ b/frame/util/multiscreenworker.h @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2018 ~ 2028 Deepin 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 MULTISCREENWORKER_H +#define MULTISCREENWORKER_H +#include "constants.h" +#include "monitor.h" +#include "utils.h" +#include "item/dockitem.h" + +#include "xcb/xcb_misc.h" + +#include +#include +#include +#include +#include + +#include + +#include + +#define WINDOWMARGIN ((m_displayMode == Dock::Efficient) ? 0 : 10) +#define ANIMATIONTIME 300 + +DGUI_USE_NAMESPACE +/** + * 多屏功能这部分看着很复杂,其实只需要把握住一个核心:及时更新数据! + * 之前测试出的诸多问题都是在切换任务栏位置,切换屏幕,主屏更改,分辨率更改等情况发生后 + * 任务栏的鼠标唤醒区域或任务栏的大小没更新或者更新时的大小还是按照原来的屏幕信息计算而来的, + */ +using DBusDock = com::deepin::dde::daemon::Dock; +using DisplayInter = com::deepin::daemon::Display; +using MonitorInter = com::deepin::daemon::display::Monitor; +using XEventMonitor = ::com::deepin::api::XEventMonitor; +using DBusLuncher = ::com::deepin::dde::Launcher; + +using namespace Dock; +class QVariantAnimation; +class QWidget; +class QTimer; +class MainWindow; + +class DockScreen : QObject +{ + Q_OBJECT +public: + explicit DockScreen(const QString ¤t, const QString &last, const QString &primary) + : m_currentScreen(current) + , m_lastScreen(last) + , m_primary(primary) + {} + explicit DockScreen(const QString &primary) + : m_currentScreen(primary) + , m_lastScreen(primary) + , m_primary(primary) + {} + inline const QString ¤t() {return m_currentScreen;} + inline const QString &last() {return m_lastScreen;} + inline const QString &primary() {return m_primary;} + + void updateDockedScreen(const QString &screenName) + { + m_lastScreen = m_currentScreen; + m_currentScreen = screenName; + } + + void updatePrimary(const QString &primary) + { + m_primary = primary; + } + +private: + QString m_currentScreen; + QString m_lastScreen; + QString m_primary; +}; + +class MultiScreenWorker : public QObject +{ + Q_OBJECT +public: + enum Flag { + Motion = 1 << 0, + Button = 1 << 1, + Key = 1 << 2 + }; + + MultiScreenWorker(QWidget *parent, DWindowManagerHelper *helper); + ~MultiScreenWorker(); + + void initShow(); + + DBusDock *dockInter() {return m_dockInter;} + + /** + * @brief lastScreen + * @return 任务栏上次所在的屏幕 + */ + inline const QString &lastScreen() {return m_ds.last();/*return m_lastScreen;*/} + /** + * @brief deskScreen + * @return 任务栏目标屏幕.可以理解为任务栏当前所在屏幕 + */ + inline const QString &deskScreen() {return m_ds.current();/*return m_currentScreen;*/} + /** + * @brief position + * @return 任务栏所在方向(上下左右) + */ + inline const Position &position() {return m_position;} + /** + * @brief displayMode + * @return 任务栏显示模式(时尚模式,高效模式) + */ + inline const DisplayMode &displayMode() {return m_displayMode;} + /** + * @brief hideMode + * @return 任务栏状态(一直显示,一直隐藏,智能隐藏) + */ + inline const HideMode &hideMode() {return m_hideMode;} + /** + * @brief hideState + * @return 任务栏的智能隐藏时的一个状态值(1显示,2隐藏,其他不处理) + */ + inline const HideState &hideState() {return m_hideState;} + /** + * @brief opacity + * @return 任务栏透明度 + */ + inline quint8 opacity() {return m_opacity * 255;} + /** + * @brief dockRect + * @param screenName 屏幕名 + * @param pos 任务栏位置 + * @param hideMode 模式 + * @param displayMode 状态 + * @return 按照给定的数据计算出任务栏所在位置 + */ + QRect dockRect(const QString &screenName, const Position &pos, const HideMode &hideMode, const DisplayMode &displayMode); + /** + * @brief dockRect + * @param screenName 屏幕名 + * @return 按照当前屏幕的当前属性给出任务栏所在区域 + */ + QRect dockRect(const QString &screenName); + + /** + * @brief handleLeaveEvent 状态为隐藏时,离开任务栏需要隐藏任务栏 + * @param event 离开事件 + */ + void handleLeaveEvent(QEvent *event); + +signals: + void opacityChanged(const quint8 value) const; + void displayModeChanegd(); + + // 更新监视区域 + void requestUpdateRegionMonitor(); + void requestUpdateFrontendGeometry(const QRect &rect); + void requestNotifyWindowManager(); + void requestUpdatePosition(const Position &fromPos, const Position &toPos); + void requestUpdateLayout(const QString &screenName); // 界面需要根据任务栏更新布局的方向 + void requestUpdateDragArea(); // 更新拖拽区域 + void requestUpdateMonitorInfo(); // 屏幕信息发生变化,需要更新任务栏大小,拖拽区域,所在屏幕,监控区域,通知窗管,通知后端, + +public slots: + void onAutoHideChanged(bool autoHide); + void updateDaemonDockSize(int dockSize); + void onDragStateChanged(bool draging); + + void handleDbusSignal(QDBusMessage); + +private slots: + // Region Monitor + void onRegionMonitorChanged(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(); + + void onWindowSizeChanged(uint value); + void primaryScreenChanged(); + + // 任务栏属性变化 + void onPositionChanged(); + void onDisplayModeChanged(); + void onHideModeChanged(); + void onHideStateChanged(); + void onOpacityChanged(const double value); + + /** + * @brief onRequestUpdateRegionMonitor 更新监听区域信息 + * 触发时机:屏幕大小,屏幕坐标,屏幕数量,发生变化 + * 任务栏位置发生变化 + * 任务栏'模式'发生变化 + */ + void onRequestUpdateRegionMonitor(); + + // 通知后端任务栏所在位置 + void onRequestUpdateFrontendGeometry(const QRect &rect); + + void onRequestNotifyWindowManager(); + void onRequestUpdatePosition(const Position &fromPos, const Position &toPos); + void onRequestUpdateDragArea(); + void onRequestUpdateMonitorInfo(); + + void updateMonitorDockedInfo(); + +private: + // 初始化数据信息 + void initMembers(); + void initConnection(); + void initUI(); + /** + * @brief showAni 任务栏显示动画 + * @param screen 显示到目标屏幕上 + */ + void showAni(const QString &screen); + /** + * @brief hideAni 任务栏隐藏动画 + * @param screen 从目标屏幕上隐藏 + */ + void hideAni(const QString &screen); + /** + * @brief changeDockPosition 做一个动画操作 + * @param lastScreen 上次任务栏所在的屏幕 + * @param deskScreen 任务栏要移动到的屏幕 + * @param fromPos 任务栏上次的方向 + * @param toPos 任务栏打算移动到的方向 + */ + void changeDockPosition(QString lastScreen, QString deskScreen, const Position &fromPos, const Position &toPos); + /** + * @brief updateDockScreenName 将任务栏所在屏幕信息进行更新,在任务栏切换屏幕显示后,这里应该被调用 + * @param screenName 目标屏幕 + */ + void updateDockScreenName(const QString &screenName); + /** + * @brief getValidScreen 获取一个当前任务栏可以停靠的屏幕,优先使用主屏 + * @return + */ + QString getValidScreen(const Position &pos); + /** + * @brief autosetDockScreen 检查一下当前屏幕所在边缘是够允许任务栏停靠,不允许的情况需要更换下一块屏幕 + */ + void autosetDockScreen(); + + void checkDaemonDockService(); + + MainWindow *parent(); + + QRect getDockShowGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode); + QRect getDockHideGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode); + + Monitor *monitorByName(const QList &list, const QString &screenName); + QScreen *screenByName(const QString &screenName); + qreal scaleByName(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); + const QPoint scaledPos(const QPoint &rawXPos); + QList validMonitorList(const QMap &map); + +private: + QWidget *m_parent; + DWindowManagerHelper *m_wmHelper; + XcbMisc *m_xcbMisc; + + // monitor screen + XEventMonitor *m_eventInter; + + // DBus interface + DBusDock *m_dockInter; + DisplayInter *m_displayInter; + DBusLuncher* m_launcherInter; + + // update monitor info + QTimer *m_monitorUpdateTimer; + + // animation + QVariantAnimation *m_showAni; + QVariantAnimation *m_hideAni; + + // 屏幕名称信息 + DockScreen m_ds; + + // 任务栏属性 + double m_opacity; + Position m_position; + HideMode m_hideMode; + HideState m_hideState; + DisplayMode m_displayMode; + /** + * @brief m_monitorInfo 屏幕信息(注意需要保证内容实时更新,且有效) + */ + QMap m_monitorInfo; + /***************不和其他流程产生交互,尽量不要动这里的变量***************/ + int m_screenRawHeight; + int m_screenRawWidth; + QString m_registerKey; + QString m_leaveRegisterKey; + bool m_aniStart; // changeDockPosition是否正在运行中 + bool m_draging; // 鼠标是否正在调整任务栏的宽度或高度 + bool m_autoHide; // 和DockSettings保持一致,可以直接使用其单例进行获取 + bool m_btnPress; // 鼠标按下时移动到唤醒区域不应该响应唤醒 + QList m_monitorRectList; // 监听唤起任务栏区域 + /*****************************************************************/ +}; + +#endif // MULTISCREENWORKER_H diff --git a/frame/util/utils.h b/frame/util/utils.h index 9bc30d223..c1b5fc1f6 100644 --- a/frame/util/utils.h +++ b/frame/util/utils.h @@ -1,3 +1,25 @@ +/* + * 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 UTILS +#define UTILS #include #include #include @@ -56,3 +78,5 @@ namespace Utils { return nullptr; } } + +#endif // UTILS diff --git a/frame/window/mainwindow.cpp b/frame/window/mainwindow.cpp old mode 100644 new mode 100755 index 79eebc917..f0c420db1 --- a/frame/window/mainwindow.cpp +++ b/frame/window/mainwindow.cpp @@ -24,7 +24,7 @@ #include "panel/mainpanelcontrol.h" #include "controller/dockitemmanager.h" #include "util/utils.h" -#include "util/docksettings.h" +#include "util/menuworker.h" #include #include @@ -40,6 +40,8 @@ #include #include +#include + #define SNI_WATCHER_SERVICE "org.kde.StatusNotifierWatcher" #define SNI_WATCHER_PATH "/StatusNotifierWatcher" @@ -48,66 +50,7 @@ #define DRAG_AREA_SIZE (5) using org::kde::StatusNotifierWatcher; - -class DragWidget : public QWidget -{ - Q_OBJECT - -private: - bool m_dragStatus; - QPoint m_resizePoint; - -public: - explicit DragWidget(QWidget *parent) : QWidget(parent) - { - setObjectName("DragWidget"); - m_dragStatus = false; - } - -signals: - void dragPointOffset(QPoint); - void dragFinished(); - -private: - void mousePressEvent(QMouseEvent *event) override - { - if (event->button() == Qt::LeftButton) { - m_resizePoint = event->globalPos(); - m_dragStatus = true; - this->grabMouse(); - } - } - - void mouseMoveEvent(QMouseEvent *event) override - { - if (m_dragStatus) { - QPoint offset = QPoint(QCursor::pos() - m_resizePoint); - emit dragPointOffset(offset); - } - } - - void mouseReleaseEvent(QMouseEvent *event) override - { - if (!m_dragStatus) - return; - - m_dragStatus = false; - releaseMouse(); - emit dragFinished(); - } - - void enterEvent(QEvent *) override - { - if (QApplication::overrideCursor() && QApplication::overrideCursor()->shape() != cursor()) { - QApplication::setOverrideCursor(cursor()); - } - } - - void leaveEvent(QEvent *) override - { - QApplication::restoreOverrideCursor(); - } -}; +using DBusDock = com::deepin::dde::daemon::Dock; const QPoint rawXPosition(const QPoint &scaledPos) { @@ -131,23 +74,18 @@ const QPoint scaledPos(const QPoint &rawXPos) MainWindow::MainWindow(QWidget *parent) : DBlurEffectWidget(parent) - , m_launched(false) , m_mainPanel(new MainPanelControl(this)) , m_platformWindowHandle(this) , m_wmHelper(DWindowManagerHelper::instance()) + , m_multiScreenWorker(new MultiScreenWorker(this, m_wmHelper)) + , m_menuWorker(new MenuWorker(m_multiScreenWorker->dockInter(), this)) , m_eventInter(new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus())) - , m_launcherInter(new DBusLuncher("com.deepin.dde.Launcher","/com/deepin/dde/Launcher",QDBusConnection::sessionBus())) - , m_positionUpdateTimer(new QTimer(this)) - , m_expandDelayTimer(new QTimer(this)) - , m_leaveDelayTimer(new QTimer(this)) , m_shadowMaskOptimizeTimer(new QTimer(this)) - , m_panelShowAni(new QVariantAnimation(this)) - , m_panelHideAni(new QVariantAnimation(this)) - , m_xcbMisc(XcbMisc::instance()) , m_dbusDaemonInterface(QDBusConnection::sessionBus().interface()) , m_sniWatcher(new StatusNotifierWatcher(SNI_WATCHER_SERVICE, SNI_WATCHER_PATH, QDBusConnection::sessionBus(), this)) , m_dragWidget(new DragWidget(this)) - , m_primaryScreenChanged(false) + , m_launched(false) + , m_dockSize(0) { setAccessibleName("mainwindow"); m_mainPanel->setAccessibleName("mainpanel"); @@ -162,15 +100,15 @@ MainWindow::MainWindow(QWidget *parent) m_platformWindowHandle.setShadowOffset(QPoint(0, 5)); m_platformWindowHandle.setShadowColor(QColor(0, 0, 0, 0.3 * 255)); - m_settings = &DockSettings::Instance(); - m_xcbMisc->set_window_type(winId(), XcbMisc::Dock); - m_size = m_settings->m_mainWindowSize; - m_mainPanel->setDisplayMode(m_settings->displayMode()); + m_mainPanel->setDisplayMode(m_multiScreenWorker->displayMode()); + initSNIHost(); initComponents(); initConnections(); - resizeMainPanelWindow(); + //TODO 优先更新一下任务栏所在屏幕 + qDebug() << m_multiScreenWorker->deskScreen(); + resetDragWindow(); m_mainPanel->setDelegate(this); for (auto item : DockItemManager::instance()->itemList()) @@ -179,170 +117,66 @@ MainWindow::MainWindow(QWidget *parent) m_dragWidget->setMouseTracking(true); m_dragWidget->setFocusPolicy(Qt::NoFocus); - m_dockPosition = m_settings->position(); - - if ((Top == m_dockPosition) || (Bottom == m_dockPosition)) { + if ((Top == m_multiScreenWorker->position()) || (Bottom == m_multiScreenWorker->position())) { m_dragWidget->setCursor(Qt::SizeVerCursor); } else { m_dragWidget->setCursor(Qt::SizeHorCursor); } - - connect(m_panelShowAni, &QVariantAnimation::valueChanged, [ this ](const QVariant & value) { - if (m_panelShowAni->state() != QPropertyAnimation::Running) - return; - // dock的宽度或高度值 - int val = value.toInt(); - // 当前dock尺寸 - const QRect windowRect = m_settings->windowRect(m_dockPosition, false); - - switch (m_dockPosition) { - case Dock::Top: - m_mainPanel->move(0, val - windowRect.height()); - QWidget::move(windowRect.topLeft()); - break; - case Dock::Bottom: - m_mainPanel->move(0, 0); - QWidget::move(windowRect.left(), windowRect.bottom() - val); - break; - case Dock::Left: - m_mainPanel->move(val - windowRect.width(), 0); - QWidget::move(windowRect.topLeft()); - break; - case Dock::Right: - m_mainPanel->move(0, 0); - QWidget::move(windowRect.right() - val, windowRect.top()); - break; - } - - if (m_dockPosition == Dock::Top || m_dockPosition == Dock::Bottom) { - QWidget::setFixedHeight(val); - } else { - QWidget::setFixedWidth(val); - } - }); - - connect(m_panelHideAni, &QVariantAnimation::valueChanged, [ this ](const QVariant & value) { - if (m_panelHideAni->state() != QPropertyAnimation::Running) - return; - - // dock的宽度或高度 - int val = value.toInt(); - // dock隐藏后的rect - const QRect windowRect = m_settings->windowRect(m_dockPosition, false, true); - const int margin = m_settings->dockMargin(); - switch (m_dockPosition) { - case Dock::Top: - m_mainPanel->move(0, val - windowRect.height()); - QWidget::move(windowRect.left(), windowRect.top() - margin); - break; - case Dock::Bottom: - m_mainPanel->move(0, 0); - QWidget::move(windowRect.left(), windowRect.bottom() - val + margin); - break; - case Dock::Left: - m_mainPanel->move(val - windowRect.width(), 0); - QWidget::move(windowRect.left() - margin, windowRect.top()); - break; - case Dock::Right: - m_mainPanel->move(0, 0); - QWidget::move(windowRect.right() - val + margin, windowRect.top()); - break; - } - - if (m_dockPosition == Dock::Top || m_dockPosition == Dock::Bottom) { - QWidget::setFixedHeight(val); - } else { - QWidget::setFixedWidth(val); - } - }); - - connect(m_panelShowAni, &QVariantAnimation::finished, [ this ]() { - const QRect windowRect = m_settings->windowRect(m_dockPosition); - QWidget::setFixedSize(windowRect.size()); - QWidget::move(windowRect.topLeft()); - m_mainPanel->move(QPoint(0, 0)); - qDebug() << "Show animation finished:" << frameGeometry(); - qDebug() << "Show animation finished not frame:" << geometry(); - QWidget::update(); - }); - - connect(m_panelHideAni, &QVariantAnimation::finished, [ this ]() { - // 动画完成更新dock位置 - m_dockPosition = m_settings->position(); - // 动画完成更新dock设置 - m_settings->posChangedUpdateSettings(); - - const QRect windowRect = m_settings->windowRect(m_dockPosition, true); - QWidget::setFixedSize(windowRect.size()); - QWidget::move(windowRect.topLeft()); - m_mainPanel->move(QPoint(0, 0)); - - qDebug() << "Hide animation finished" << frameGeometry(); - qDebug() << "Hide animation finished not frame:" << geometry(); - QWidget::update(); - }); - - updateRegionMonitorWatch(); } MainWindow::~MainWindow() { - delete m_xcbMisc; + } void MainWindow::launch() { - m_launched = true; - qApp->processEvents(); - QWidget::move(m_settings->windowRect(m_dockPosition).topLeft()); - setVisible(true); - updatePanelVisible(); - resetPanelEnvironment(); - // 用于更新mainwindow圆角 - m_shadowMaskOptimizeTimer->start(); + setVisible(false); + QTimer::singleShot(400, this, [&] { + m_launched = true; + qApp->processEvents(); + initShow(); + }); } -bool MainWindow::event(QEvent *e) +void MainWindow::initShow() { -// switch (e->type()) { -// case QEvent::Move: -// if (!e->spontaneous()) -// QTimer::singleShot(100, this, &MainWindow::positionCheck); -// break; -// default:; -// } + setVisible(true); - return QWidget::event(e); + m_multiScreenWorker->initShow(); + + m_shadowMaskOptimizeTimer->start(); } void MainWindow::showEvent(QShowEvent *e) { QWidget::showEvent(e); -// connect(qGuiApp, &QGuiApplication::primaryScreenChanged, -// windowHandle(), [this](QScreen * new_screen) { -// QScreen *old_screen = windowHandle()->screen(); -// windowHandle()->setScreen(new_screen); -// // 屏幕变化后可能导致控件缩放比变化,此时应该重设控件位置大小 -// // 比如:窗口大小为 100 x 100, 显示在缩放比为 1.0 的屏幕上,此时窗口的真实大小 = 100x100 -// // 随后窗口被移动到了缩放比为 2.0 的屏幕上,应该将真实大小改为 200x200。另外,只能使用 -// // QPlatformWindow直接设置大小来绕过QWidget和QWindow对新旧geometry的比较。 -// const qreal scale = devicePixelRatioF(); -// const QPoint screenPos = new_screen->geometry().topLeft(); -// const QPoint posInScreen = this->pos() - old_screen->geometry().topLeft(); -// const QPoint pos = screenPos + posInScreen * scale; -// const QSize size = this->size() * scale; -// windowHandle()->handle()->setGeometry(QRect(pos, size)); -// }, Qt::UniqueConnection); + // connect(qGuiApp, &QGuiApplication::primaryScreenChanged, + // windowHandle(), [this](QScreen * new_screen) { + // QScreen *old_screen = windowHandle()->screen(); + // windowHandle()->setScreen(new_screen); + // // 屏幕变化后可能导致控件缩放比变化,此时应该重设控件位置大小 + // // 比如:窗口大小为 100 x 100, 显示在缩放比为 1.0 的屏幕上,此时窗口的真实大小 = 100x100 + // // 随后窗口被移动到了缩放比为 2.0 的屏幕上,应该将真实大小改为 200x200。另外,只能使用 + // // QPlatformWindow直接设置大小来绕过QWidget和QWindow对新旧geometry的比较。 + // const qreal scale = devicePixelRatioF(); + // const QPoint screenPos = new_screen->geometry().topLeft(); + // const QPoint posInScreen = this->pos() - old_screen->geometry().topLeft(); + // const QPoint pos = screenPos + posInScreen * scale; + // const QSize size = this->size() * scale; -// windowHandle()->setScreen(qGuiApp->primaryScreen()); + // windowHandle()->handle()->setGeometry(QRect(pos, size)); + // }, Qt::UniqueConnection); + + // windowHandle()->setScreen(qGuiApp->primaryScreen()); } void MainWindow::mousePressEvent(QMouseEvent *e) { e->ignore(); - if (e->button() == Qt::RightButton && m_settings->m_menuVisible) { - m_settings->showDockSettingsMenu(); + if (e->button() == Qt::RightButton && m_menuWorker->menuEnable()) { + m_menuWorker->showDockSettingsMenu(); return; } } @@ -367,26 +201,24 @@ void MainWindow::enterEvent(QEvent *e) void MainWindow::mouseMoveEvent(QMouseEvent *e) { + Q_UNUSED(e); //重写mouseMoveEvent 解决bug12866 leaveEvent事件失效 } +void MainWindow::moveEvent(QMoveEvent *event) +{ + Q_UNUSED(event); +} + void MainWindow::leaveEvent(QEvent *e) { QWidget::leaveEvent(e); - if (m_panelHideAni->state() == QPropertyAnimation::Running) - return; - - m_expandDelayTimer->stop(); - m_leaveDelayTimer->start(); + return m_multiScreenWorker->handleLeaveEvent(e); } void MainWindow::dragEnterEvent(QDragEnterEvent *e) { QWidget::dragEnterEvent(e); - - if (m_settings->hideState() != Show) { - m_expandDelayTimer->start(); - } } void MainWindow::initSNIHost() @@ -406,22 +238,9 @@ void MainWindow::initSNIHost() void MainWindow::initComponents() { - m_positionUpdateTimer->setSingleShot(true); - m_positionUpdateTimer->setInterval(20); - m_positionUpdateTimer->start(); - - m_expandDelayTimer->setSingleShot(true); - m_expandDelayTimer->setInterval(m_settings->expandTimeout()); - - m_leaveDelayTimer->setSingleShot(true); - m_leaveDelayTimer->setInterval(m_settings->narrowTimeout()); - m_shadowMaskOptimizeTimer->setSingleShot(true); m_shadowMaskOptimizeTimer->setInterval(100); - m_panelShowAni->setEasingCurve(QEasingCurve::InOutCubic); - m_panelHideAni->setEasingCurve(QEasingCurve::InOutCubic); - QTimer::singleShot(1, this, &MainWindow::compositeChanged); themeTypeChanged(DGuiApplicationHelper::instance()->themeType()); @@ -432,162 +251,49 @@ void MainWindow::compositeChanged() const bool composite = m_wmHelper->hasComposite(); setComposite(composite); - // NOTE(justforlxz): On the sw platform, there is an unstable - // display position error, disable animation solution -#ifndef DISABLE_SHOW_ANIMATION - const int duration = composite ? 300 : 0; -#else - const int duration = 0; -#endif - - m_panelHideAni->setDuration(duration); - m_panelShowAni->setDuration(duration); - m_shadowMaskOptimizeTimer->start(); } -void MainWindow::internalMove(const QPoint &p) -{ - const bool isHide = m_settings->hideState() == HideState::Hide && !testAttribute(Qt::WA_UnderMouse); - const bool pos_adjust = m_settings->hideMode() != HideMode::KeepShowing && - isHide && - m_panelShowAni->state() == QVariantAnimation::Stopped; - if (!pos_adjust) { - m_mainPanel->move(0, 0); - return QWidget::move(p); - } -} - void MainWindow::initConnections() { - connect(m_settings, &DockSettings::primaryScreenChanged, [&]() { - m_primaryScreenChanged = true; - updatePosition(); - m_primaryScreenChanged = false; - }); - connect(m_settings, &DockSettings::positionChanged, this, &MainWindow::positionChanged); - connect(m_settings, &DockSettings::autoHideChanged, m_leaveDelayTimer, static_cast(&QTimer::start)); - connect(m_settings, &DockSettings::windowGeometryChanged, this, &MainWindow::updateGeometry, Qt::DirectConnection); - connect(m_settings, &DockSettings::trayCountChanged, this, &MainWindow::getTrayVisableItemCount, Qt::DirectConnection); - connect(m_settings, &DockSettings::windowHideModeChanged, this, &MainWindow::setStrutPartial, Qt::QueuedConnection); - connect(m_settings, &DockSettings::windowHideModeChanged, [this] { resetPanelEnvironment(); }); - connect(m_settings, &DockSettings::windowHideModeChanged, m_leaveDelayTimer, static_cast(&QTimer::start)); - connect(m_settings, &DockSettings::windowVisibleChanged, this, &MainWindow::updatePanelVisible, Qt::QueuedConnection); - connect(m_settings, &DockSettings::displayModeChanegd, m_positionUpdateTimer, static_cast(&QTimer::start)); - connect(&DockSettings::Instance(), &DockSettings::opacityChanged, this, &MainWindow::setMaskAlpha); - connect(m_settings, &DockSettings::displayModeChanegd, this, &MainWindow::updateDisplayMode, Qt::QueuedConnection); - - connect(m_positionUpdateTimer, &QTimer::timeout, this, &MainWindow::updatePosition, Qt::QueuedConnection); - connect(m_expandDelayTimer, &QTimer::timeout, this, &MainWindow::expand, Qt::QueuedConnection); - connect(m_leaveDelayTimer, &QTimer::timeout, this, &MainWindow::updatePanelVisible, Qt::QueuedConnection); connect(m_shadowMaskOptimizeTimer, &QTimer::timeout, this, &MainWindow::adjustShadowMask, Qt::QueuedConnection); - connect(m_panelHideAni, &QPropertyAnimation::finished, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); - connect(m_panelShowAni, &QPropertyAnimation::finished, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); - connect(m_panelHideAni, &QPropertyAnimation::finished, this, &MainWindow::panelGeometryChanged); - connect(m_panelShowAni, &QPropertyAnimation::finished, this, &MainWindow::panelGeometryChanged); - connect(m_wmHelper, &DWindowManagerHelper::hasCompositeChanged, this, &MainWindow::compositeChanged, Qt::QueuedConnection); connect(&m_platformWindowHandle, &DPlatformWindowHandle::frameMarginsChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); - if (m_dbusDaemonInterface && m_dbusDaemonInterface->isValid()) - connect(m_dbusDaemonInterface, &QDBusConnectionInterface::serviceOwnerChanged, this, &MainWindow::onDbusNameOwnerChanged); + connect(m_dbusDaemonInterface, &QDBusConnectionInterface::serviceOwnerChanged, this, &MainWindow::onDbusNameOwnerChanged); connect(DockItemManager::instance(), &DockItemManager::itemInserted, m_mainPanel, &MainPanelControl::insertItem, Qt::DirectConnection); connect(DockItemManager::instance(), &DockItemManager::itemRemoved, m_mainPanel, &MainPanelControl::removeItem, Qt::DirectConnection); connect(DockItemManager::instance(), &DockItemManager::itemUpdated, m_mainPanel, &MainPanelControl::itemUpdated, Qt::DirectConnection); - connect(DockItemManager::instance(), &DockItemManager::requestRefershWindowVisible, this, &MainWindow::updatePanelVisible, Qt::QueuedConnection); - connect(DockItemManager::instance(), &DockItemManager::requestWindowAutoHide, m_settings, &DockSettings::setAutoHide); + connect(DockItemManager::instance(), &DockItemManager::requestWindowAutoHide, m_menuWorker, &MenuWorker::setAutoHide); 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_dragWidget, &DragWidget::dragPointOffset, this, &MainWindow::onMainWindowSizeChanged); connect(m_dragWidget, &DragWidget::dragFinished, this, &MainWindow::onDragFinished); + connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &MainWindow::themeTypeChanged); - connect(m_eventInter, &XEventMonitor::CursorMove, this, &MainWindow::onRegionMonitorChanged); - connect(m_settings, &DockSettings::requestUpdateRegionWatch, this, &MainWindow::updateRegionMonitorWatch); -} -//const QPoint MainWindow::x11GetWindowPos() -//{ -// const auto disp = QX11Info::display(); + connect(m_menuWorker, &MenuWorker::trayCountChanged, this, &MainWindow::getTrayVisableItemCount, Qt::DirectConnection); + connect(m_menuWorker, &MenuWorker::autoHideChanged, m_multiScreenWorker, &MultiScreenWorker::onAutoHideChanged); -// unsigned int unused; -// int x; -// int y; -// Window unused_window; + connect(m_multiScreenWorker, &MultiScreenWorker::opacityChanged, this, &MainWindow::setMaskAlpha, Qt::QueuedConnection); + connect(m_multiScreenWorker, &MultiScreenWorker::displayModeChanegd, this, &MainWindow::updateDisplayMode, Qt::QueuedConnection); -// XGetGeometry(disp, winId(), &unused_window, &x, &y, &unused, &unused, &unused, &unused); -// XFlush(disp); + // 更新任务栏内容展示 + connect(m_multiScreenWorker, &MultiScreenWorker::requestUpdateLayout, this, [ = ](const QString & screenName) { + m_mainPanel->setFixedSize(m_multiScreenWorker->dockRect(screenName, m_multiScreenWorker->position(), HideMode::KeepShowing, m_multiScreenWorker->displayMode()).size()); + m_mainPanel->move(0, 0); + m_mainPanel->setDisplayMode(m_multiScreenWorker->displayMode()); + m_mainPanel->setPositonValue(m_multiScreenWorker->position()); + m_mainPanel->update(); + }); -// return QPoint(x, y); -//} - -//void MainWindow::x11MoveWindow(const int x, const int y) -//{ -// const auto disp = QX11Info::display(); - -// XMoveWindow(disp, winId(), x, y); -// XFlush(disp); -//} - -//void MainWindow::x11MoveResizeWindow(const int x, const int y, const int w, const int h) -//{ -// const auto disp = QX11Info::display(); - -// XMoveResizeWindow(disp, winId(), x, y, w, h); -// XFlush(disp); -//} - -void MainWindow::positionChanged() -{ - // paly hide animation and disable other animation - qDebug() << "start positionChange:" << frameGeometry(); - clearStrutPartial(); - - // 需要在narrow之前执行,保证动画结束后能后更新界面布局的方向 - connect(m_panelHideAni, &QVariantAnimation::finished, this, &MainWindow::newPositionExpand); - - narrow(); -} - -void MainWindow::updatePosition() -{ - // all update operation need pass by timer - // Q_ASSERT(sender() == m_positionUpdateTimer); - - //clearStrutPartial(); - updateGeometry(); -} - -void MainWindow::updateGeometry() -{ - // DockDisplayMode and DockPosition MUST be set before invoke setFixedSize method of MainPanel - - //为了防止当后端发送错误值,然后发送正确值时,任务栏没有移动在相应的位置 - //当qt没有获取到屏幕资源时候,move函数会失效。可以直接return - if (m_settings->primaryRect().width() == 0 || m_settings->primaryRect().height() == 0) { - return; - } - - setStrutPartial(); - - m_mainPanel->setDisplayMode(m_settings->displayMode()); - m_mainPanel->setPositonValue(m_dockPosition); - - bool isHide = m_settings->hideState() == Hide && !testAttribute(Qt::WA_UnderMouse); - - const QRect windowRect = m_settings->windowRect(m_dockPosition, isHide); - - internalMove(windowRect.topLeft()); - - if (!m_primaryScreenChanged || m_settings->hideState() != Hide) { - QWidget::move(windowRect.topLeft()); - QWidget::setFixedSize(m_settings->m_mainWindowSize); - } - - resizeMainPanelWindow(); - - m_mainPanel->update(); + // 更新拖拽区域 + connect(m_multiScreenWorker, &MultiScreenWorker::requestUpdateDragArea, this, &MainWindow::resetDragWindow); } void MainWindow::getTrayVisableItemCount() @@ -595,225 +301,6 @@ void MainWindow::getTrayVisableItemCount() m_mainPanel->getTrayVisableItemCount(); } -void MainWindow::newPositionExpand() -{ - // set strut - setStrutPartial(); - - // reset to right environment when animation finished - m_mainPanel->setPositonValue(m_dockPosition); - resetPanelEnvironment(); - - if ((Top == m_dockPosition) || (Bottom == m_dockPosition)) { - m_dragWidget->setCursor(Qt::SizeVerCursor); - } else { - m_dragWidget->setCursor(Qt::SizeHorCursor); - } - - disconnect(m_panelHideAni, &QVariantAnimation::finished, this, &MainWindow::newPositionExpand); - - updatePanelVisible(); -} - -void MainWindow::clearStrutPartial() -{ - m_xcbMisc->clear_strut_partial(winId()); -} - -void MainWindow::setStrutPartial() -{ - // first, clear old strut partial - clearStrutPartial(); - - // reset env - //resetPanelEnvironment(true); - - if (m_settings->hideMode() != Dock::KeepShowing) - return; - - const auto ratio = devicePixelRatioF(); - const int maxScreenHeight = m_settings->screenRawHeight(); - const int maxScreenWidth = m_settings->screenRawWidth(); - const QPoint &p = rawXPosition(m_settings->windowRect(m_dockPosition).topLeft()); - const QSize &s = m_settings->windowSize(); - const QRect &primaryRawRect = m_settings->currentRawRect(); - - XcbMisc::Orientation orientation = XcbMisc::OrientationTop; - uint strut = 0; - uint strutStart = 0; - uint strutEnd = 0; - - QRect strutArea(0, 0, maxScreenWidth, maxScreenHeight); - switch (m_dockPosition) { - case Position::Top: - orientation = XcbMisc::OrientationTop; - strut = p.y() + s.height() * ratio; - strutStart = p.x(); - strutEnd = qMin(qRound(p.x() + s.width() * ratio), primaryRawRect.right()); - strutArea.setLeft(strutStart); - strutArea.setRight(strutEnd); - strutArea.setBottom(strut); - break; - case Position::Bottom: - orientation = XcbMisc::OrientationBottom; - strut = maxScreenHeight - p.y(); - strutStart = p.x(); - strutEnd = qMin(qRound(p.x() + s.width() * ratio), primaryRawRect.right()); - strutArea.setLeft(strutStart); - strutArea.setRight(strutEnd); - strutArea.setTop(p.y()); - break; - case Position::Left: - orientation = XcbMisc::OrientationLeft; - strut = p.x() + s.width() * ratio; - strutStart = p.y(); - strutEnd = qMin(qRound(p.y() + s.height() * ratio), primaryRawRect.bottom()); - strutArea.setTop(strutStart); - strutArea.setBottom(strutEnd); - strutArea.setRight(strut); - break; - case Position::Right: - orientation = XcbMisc::OrientationRight; - strut = maxScreenWidth - p.x(); - strutStart = p.y(); - strutEnd = qMin(qRound(p.y() + s.height() * ratio), primaryRawRect.bottom()); - strutArea.setTop(strutStart); - strutArea.setBottom(strutEnd); - strutArea.setLeft(p.x()); - break; - default: - Q_ASSERT(false); - } - - // pass if strut area is intersect with other screen - //优化了文件管理的代码 会导致bug 15351 需要注释一下代码 - // int count = 0; - // const QRect pr = m_settings->currentRawRect(); - // for (auto *screen : qApp->screens()) { - // const QRect sr = screen->geometry(); - // if (sr == pr) - // continue; - - // if (sr.intersects(strutArea)) - // ++count; - // } - // if (count > 0) { - // qWarning() << "strutArea is intersects with another screen."; - // qWarning() << maxScreenHeight << maxScreenWidth << m_dockPosition << p << s; - // return; - // } - - m_xcbMisc->set_strut_partial(winId(), orientation, strut + m_settings->dockMargin() * ratio, strutStart, strutEnd); -} - -void MainWindow::expand() -{ - qDebug() << "expand started"; - if (m_panelHideAni->state() == QPropertyAnimation::Running) { - m_panelHideAni->stop(); - emit m_panelHideAni->finished(); - } - - const auto showAniState = m_panelShowAni->state(); - - int startValue = 0; - int endValue = 0; - - resetPanelEnvironment(); - if (showAniState != QPropertyAnimation::Running && pos() != m_panelShowAni->currentValue()) { - const QRect windowRect = m_settings->windowRect(m_dockPosition); - - startValue = (m_dockPosition == Top || m_dockPosition == Bottom) ? height() : width(); - endValue = (m_dockPosition == Top || m_dockPosition == Bottom) ? windowRect.height() : windowRect.width(); - - qDebug() << "expand " << "start value:" << startValue - << "end value:" << endValue; - - if (startValue > DOCK_MAX_SIZE || endValue > DOCK_MAX_SIZE) { - return; - } - - if (startValue > endValue) - return; - - m_panelShowAni->setStartValue(startValue); - m_panelShowAni->setEndValue(endValue); - m_panelShowAni->start(); - qDebug() << "show ani start"; - m_shadowMaskOptimizeTimer->start(); - m_settings->posChangedUpdateSettings(); - } -} - -void MainWindow::narrow() -{ - qDebug() << "narrow started"; - int startValue = (m_dockPosition == Top || m_dockPosition == Bottom) ? height() : width(); - - qDebug() << "narrow " << "start value:" << startValue; - m_panelShowAni->stop(); - m_panelHideAni->setStartValue(startValue); - m_panelHideAni->setEndValue(0); - m_panelHideAni->start(); -} - -void MainWindow::resetPanelEnvironment() -{ - if (!m_launched) - return; - - resizeMainPanelWindow(); - updateRegionMonitorWatch(); - if (m_size != m_settings->m_mainWindowSize) { - m_size = m_settings->m_mainWindowSize; - setStrutPartial(); - } -} - -void MainWindow::updatePanelVisible() -{ - if (m_settings->hideMode() == KeepShowing) { - if (!m_registerKey.isEmpty()) { - m_eventInter->UnregisterArea(m_registerKey); - qDebug() << "register area clear"; - //清空registerKey - m_registerKey.clear(); - } - return expand(); - } - - if (m_registerKey.isEmpty()) { - updateRegionMonitorWatch(); - } - - const Dock::HideState state = m_settings->hideState(); - - if (state == Hide && m_settings->autoHide()) { - QRectF r(pos(), size()); - const int margin = m_settings->dockMargin(); - switch (m_dockPosition) { - case Dock::Top: - r.setY(r.y() - margin); - break; - case Dock::Bottom: - r.setHeight(r.height() + margin); - break; - case Dock::Left: - r.setX(r.x() - margin); - break; - case Dock::Right: - r.setWidth(r.width() + margin); - break; - } - if (!r.contains(QCursor::pos())) { - qDebug() << "hide narrow"; - return narrow(); - } - } - - return expand(); -} - void MainWindow::adjustShadowMask() { if (!m_launched) @@ -823,27 +310,14 @@ void MainWindow::adjustShadowMask() return; const bool composite = m_wmHelper->hasComposite(); - const bool isFasion = m_settings->displayMode() == Fashion; + const bool isFasion = m_multiScreenWorker->displayMode() == Fashion; DStyleHelper dstyle(style()); const int radius = dstyle.pixelMetric(DStyle::PM_TopLevelWindowRadius); + m_platformWindowHandle.setWindowRadius(composite && isFasion ? radius : 0); } -void MainWindow::positionCheck() -{ - if (m_positionUpdateTimer->isActive()) - return; - - const QPoint scaledFrontPos = scaledPos(m_settings->frontendWindowRect().topLeft()); - - if (QPoint(pos() - scaledFrontPos).manhattanLength() < 2) - return; - - // this may cause some position error and animation caton - // internalMove(); -} - void MainWindow::onDbusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner) { Q_UNUSED(oldOwner); @@ -858,7 +332,7 @@ void MainWindow::setEffectEnabled(const bool enabled) { setMaskColor(AutoColor); - setMaskAlpha(DockSettings::Instance().Opacity()); + setMaskAlpha(m_multiScreenWorker->opacity()); m_platformWindowHandle.setBorderWidth(enabled ? 1 : 0); } @@ -873,20 +347,9 @@ bool MainWindow::appIsOnDock(const QString &appDesktop) return DockItemManager::instance()->appIsOnDock(appDesktop); } -void MainWindow::resizeMainWindow() +void MainWindow::resetDragWindow() { - QSize size = m_settings->windowSize(); - const QRect windowRect = m_settings->windowRect(m_dockPosition, false); - internalMove(windowRect.topLeft()); - resizeMainPanelWindow(); - QWidget::setFixedSize(size); -} - -void MainWindow::resizeMainPanelWindow() -{ - m_mainPanel->setFixedSize(m_settings->m_mainWindowSize); - - switch (m_dockPosition) { + switch (m_multiScreenWorker->position()) { case Dock::Top: m_dragWidget->setGeometry(0, height() - DRAG_AREA_SIZE, width(), DRAG_AREA_SIZE); break; @@ -899,65 +362,81 @@ void MainWindow::resizeMainPanelWindow() case Dock::Right: m_dragWidget->setGeometry(0, 0, DRAG_AREA_SIZE, height()); break; - Q_UNREACHABLE(); + } + + if (m_dockSize == 0) + m_dockSize = m_multiScreenWorker->dockRect(m_multiScreenWorker->deskScreen()).height(); + + // 通知窗管和后端更新数据 + m_multiScreenWorker->updateDaemonDockSize(m_dockSize); + m_multiScreenWorker->requestNotifyWindowManager(); + + if ((Top == m_multiScreenWorker->position()) || (Bottom == m_multiScreenWorker->position())) { + m_dragWidget->setCursor(Qt::SizeVerCursor); + } else { + m_dragWidget->setCursor(Qt::SizeHorCursor); } } void MainWindow::updateDisplayMode() { - m_mainPanel->setDisplayMode(m_settings->displayMode()); - setStrutPartial(); + m_mainPanel->setDisplayMode(m_multiScreenWorker->displayMode()); adjustShadowMask(); - updateRegionMonitorWatch(); } void MainWindow::onMainWindowSizeChanged(QPoint offset) { - if (Dock::Top == m_dockPosition) { - m_settings->m_mainWindowSize.setHeight(qBound(MAINWINDOW_MIN_SIZE, m_size.height() + offset.y(), MAINWINDOW_MAX_SIZE)); - m_settings->m_mainWindowSize.setWidth(width()); - } else if (Dock::Bottom == m_dockPosition) { - m_settings->m_mainWindowSize.setHeight(qBound(MAINWINDOW_MIN_SIZE, m_size.height() - offset.y(), MAINWINDOW_MAX_SIZE)); - m_settings->m_mainWindowSize.setWidth(width()); - } else if (Dock::Left == m_dockPosition) { - m_settings->m_mainWindowSize.setHeight(height()); - m_settings->m_mainWindowSize.setWidth(qBound(MAINWINDOW_MIN_SIZE, m_size.width() + offset.x(), MAINWINDOW_MAX_SIZE)); - } else { - m_settings->m_mainWindowSize.setHeight(height()); - m_settings->m_mainWindowSize.setWidth(qBound(MAINWINDOW_MIN_SIZE, m_size.width() - offset.x(), MAINWINDOW_MAX_SIZE)); + const QRect &rect = m_multiScreenWorker->dockRect(m_multiScreenWorker->deskScreen()); + + QRect newRect; + switch (m_multiScreenWorker->position()) { + case Top: { + newRect.setX(rect.x()); + newRect.setY(rect.y()); + newRect.setWidth(rect.width()); + newRect.setHeight(qBound(MAINWINDOW_MIN_SIZE, rect.height() + offset.y(), MAINWINDOW_MAX_SIZE)); + + m_dockSize = newRect.height(); + } + 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)); + + m_dockSize = newRect.height(); + } + 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()); + + m_dockSize = newRect.width(); + } + 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()); + + m_dockSize = newRect.width(); + } + break; } - resizeMainWindow(); - m_settings->updateFrontendGeometry(); + // 更新界面大小 + m_mainPanel->setFixedSize(newRect.size()); + setFixedSize(newRect.size()); + move(newRect.topLeft()); } void MainWindow::onDragFinished() { - if (m_size == m_settings->m_mainWindowSize) - return; - - m_size = m_settings->m_mainWindowSize; - - if (m_settings->displayMode() == Fashion) { - if (Dock::Top == m_dockPosition || Dock::Bottom == m_dockPosition) { - m_settings->m_dockInter->setWindowSizeFashion(m_settings->m_mainWindowSize.height()); - m_settings->m_dockInter->setWindowSize(m_settings->m_mainWindowSize.height()); - } else { - m_settings->m_dockInter->setWindowSizeFashion(m_settings->m_mainWindowSize.width()); - m_settings->m_dockInter->setWindowSize(m_settings->m_mainWindowSize.width()); - } - } else { - if (Dock::Top == m_dockPosition || Dock::Bottom == m_dockPosition) { - m_settings->m_dockInter->setWindowSizeEfficient(m_settings->m_mainWindowSize.height()); - m_settings->m_dockInter->setWindowSize(m_settings->m_mainWindowSize.height()); - } else { - m_settings->m_dockInter->setWindowSizeEfficient(m_settings->m_mainWindowSize.width()); - m_settings->m_dockInter->setWindowSize(m_settings->m_mainWindowSize.width()); - } - } - - - setStrutPartial(); + resetDragWindow(); } void MainWindow::themeTypeChanged(DGuiApplicationHelper::ColorType themeType) @@ -971,153 +450,5 @@ void MainWindow::themeTypeChanged(DGuiApplicationHelper::ColorType themeType) } } -void MainWindow::onRegionMonitorChanged(int x, int y, const QString &key) -{ - if (m_registerKey != key) - return; - - // 同一个坐标,只响应一次 - static QPoint lastPos(0, 0); - if (lastPos == QPoint(x, y)) { - return; - } - lastPos = QPoint(x, y); - - QScreen *screen = Utils::screenAt(QPoint(x, y)); - if (!screen) - return; - - QRect screenRect = screen->geometry(); - qDebug() << y << screenRect.y() << screenRect.y() + screenRect.height() / 2; - switch (m_dockPosition) { - case Top: - if (y > screenRect.y() + screenRect.height() / 2) - return; - break; - case Bottom: - if (y < screenRect.y() + screenRect.height() / 2) - return; - break; - case Left: - if (x > screenRect.x() + screenRect.width() / 2) - return; - break; - case Right: - if (x < screenRect.x() + screenRect.width() / 2) - return; - } - - if (screen->name() == m_settings->currentDockScreen()) { - if (m_settings->hideMode() == KeepShowing) - return; - - if (m_panelShowAni->state() == QPropertyAnimation::Running) - return; - - // 一直隐藏模式不用通过时间延迟的方式调用,影响离开动画的响应 - expand(); - } else { - // 移动Dock至相应屏相应位置 - if (m_launcherInter->IsVisible())//启动器显示,则dock不显示 - return; - - if (m_settings->setDockScreen(screen->name())) { - if (m_settings->hideMode() == KeepShowing || m_settings->hideMode() == SmartHide) { - narrow(); - newPositionExpand(); - } else { - int screenWidth = screen->size().width(); - int screenHeight = screen->size().height(); - switch (m_dockPosition) { - case Dock::Top: - case Dock::Bottom: - setFixedWidth(screenWidth); - break; - case Dock::Left: - case Dock::Right: - setFixedHeight(screenHeight); - break; - } - expand(); - } - } - } -} - -void MainWindow::updateRegionMonitorWatch() -{ - if (!m_registerKey.isEmpty()) { - bool ret = m_eventInter->UnregisterArea(m_registerKey); - qDebug() << "register area clear:" << ret; - m_registerKey.clear(); - } - - const int flags = Motion | Button | Key; - - QList screensRect = m_settings->monitorsRect(); - QList monitorAreas; - - int val = 3; - int x, y, w, h; - - auto func = [&](MonitRect & monitRect) { - monitRect.x1 = x; - monitRect.y1 = y; - monitRect.x2 = x + w; - monitRect.y2 = y + h; - monitorAreas << monitRect; - }; - - if (screensRect.size()) { - MonitRect monitRect; - switch (m_dockPosition) { - case Dock::Top: { - for (QRect rect : screensRect) { - x = rect.x(); - y = rect.y(); - w = rect.width(); - h = val; - func(monitRect); - } - } - break; - case Dock::Bottom: { - for (QRect rect : screensRect) { - x = rect.x(); - y = rect.y() + rect.height() - val; - w = rect.width(); - h = val; - func(monitRect); - } - } - break; - case Dock::Left: { - for (QRect rect : screensRect) { - x = rect.x(); - y = rect.y(); - w = val; - h = rect.height(); - func(monitRect); - } - } - break; - case Dock::Right: { - for (QRect rect : screensRect) { - x = rect.x() + rect.width() - val; - y = rect.y(); - w = val; - h = rect.height(); - func(monitRect); - } - } - break; - } - m_registerKey = m_eventInter->RegisterAreas(monitorAreas, flags); - qDebug() << "register key" << m_registerKey; - } else { - m_registerKey = m_eventInter->RegisterFullScreen(); - qDebug() << "register full screen" << m_registerKey; - } -} #include "mainwindow.moc" diff --git a/frame/window/mainwindow.h b/frame/window/mainwindow.h index 67f2b323c..db38f083a 100644 --- a/frame/window/mainwindow.h +++ b/frame/window/mainwindow.h @@ -26,9 +26,9 @@ #include "xcb/xcb_misc.h" #include "dbus/sni/statusnotifierwatcher_interface.h" #include "panel/mainpanelcontrol.h" +#include "util/multiscreenworker.h" #include -#include #include #include @@ -40,13 +40,69 @@ DWIDGET_USE_NAMESPACE using XEventMonitor = ::com::deepin::api::XEventMonitor; -using DBusLuncher = ::com::deepin::dde::Launcher; -class DockSettings; -class DragWidget; class MainPanel; class MainPanelControl; class QTimer; +class MenuWorker; +class DragWidget : public QWidget +{ + Q_OBJECT + +private: + bool m_dragStatus; + QPoint m_resizePoint; + +public: + DragWidget(QWidget *parent = nullptr) : QWidget(parent) + { + setObjectName("DragWidget"); + m_dragStatus = false; + } + +signals: + void dragPointOffset(QPoint); + void dragFinished(); + +private: + void mousePressEvent(QMouseEvent *event) override + { + if (event->button() == Qt::LeftButton) { + m_resizePoint = event->globalPos(); + m_dragStatus = true; + this->grabMouse(); + } + } + + void mouseMoveEvent(QMouseEvent *) override + { + if (m_dragStatus) { + QPoint offset = QPoint(QCursor::pos() - m_resizePoint); + emit dragPointOffset(offset); + } + } + + void mouseReleaseEvent(QMouseEvent *) override + { + if (!m_dragStatus) + return; + + m_dragStatus = false; + releaseMouse(); + emit dragFinished(); + } + + void enterEvent(QEvent *) override + { + QApplication::setOverrideCursor(cursor()); + } + + void leaveEvent(QEvent *) override + { + QApplication::setOverrideCursor(Qt::ArrowCursor); + } +}; + class MainWindow : public DBlurEffectWidget, public MainPanelDelegate { Q_OBJECT @@ -59,19 +115,23 @@ class MainWindow : public DBlurEffectWidget, public MainPanelDelegate public: explicit MainWindow(QWidget *parent = nullptr); - ~MainWindow(); + ~MainWindow() override; void setEffectEnabled(const bool enabled); void setComposite(const bool hasComposite); friend class MainPanel; friend class MainPanelControl; + MainPanelControl *panel() {return m_mainPanel;} + DragWidget *dragWidget() {return m_dragWidget;} + public slots: void launch(); + // 第一次显示 + void initShow(); private: using QWidget::show; - bool event(QEvent *e) override; void showEvent(QShowEvent *e) override; void mousePressEvent(QMouseEvent *e) override; void keyPressEvent(QKeyEvent *e) override; @@ -79,75 +139,52 @@ private: void leaveEvent(QEvent *e) override; void dragEnterEvent(QDragEnterEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; + void moveEvent(QMoveEvent *event) override; void initSNIHost(); void initComponents(); void initConnections(); - void resizeMainWindow(); - void resizeMainPanelWindow(); -// const QPoint x11GetWindowPos(); -// 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) override; - void onRegionMonitorChanged(int x, int y, const QString &key); - void updateRegionMonitorWatch(); void getTrayVisableItemCount(); signals: void panelGeometryChanged(); +public slots: + void resetDragWindow(); + private slots: - void positionChanged(); - void updatePosition(); - void updateGeometry(); - void clearStrutPartial(); - void setStrutPartial(); void compositeChanged(); - void internalMove(const QPoint &p); void updateDisplayMode(); - void expand(); - void narrow(); - void resetPanelEnvironment(); - void updatePanelVisible(); - void adjustShadowMask(); - void positionCheck(); void onDbusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); void onMainWindowSizeChanged(QPoint offset); void onDragFinished(); void themeTypeChanged(DGuiApplicationHelper::ColorType themeType); - void newPositionExpand(); - private: - bool m_launched; MainPanelControl *m_mainPanel; DPlatformWindowHandle m_platformWindowHandle; DWindowManagerHelper *m_wmHelper; + MultiScreenWorker *m_multiScreenWorker; + MenuWorker *m_menuWorker; XEventMonitor *m_eventInter; - DBusLuncher* m_launcherInter; - QString m_registerKey{""}; - QTimer *m_positionUpdateTimer; - QTimer *m_expandDelayTimer; - QTimer *m_leaveDelayTimer; - QTimer *m_shadowMaskOptimizeTimer; - QVariantAnimation *m_panelShowAni; - QVariantAnimation *m_panelHideAni; - XcbMisc *m_xcbMisc; - DockSettings *m_settings; + QTimer *m_shadowMaskOptimizeTimer; QDBusConnectionInterface *m_dbusDaemonInterface; org::kde::StatusNotifierWatcher *m_sniWatcher; QString m_sniHostService; - QSize m_size; DragWidget *m_dragWidget; - Position m_dockPosition; - bool m_primaryScreenChanged; + + bool m_launched; + int m_dockSize; + QString m_registerKey; + QStringList m_registerKeys; }; #endif // MAINWINDOW_H