// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "mainwindow.h" #include "mainpanelcontrol.h" #include "dockitemmanager.h" #include "menuworker.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SNI_WATCHER_SERVICE "org.kde.StatusNotifierWatcher" #define SNI_WATCHER_PATH "/StatusNotifierWatcher" #define MAINWINDOW_MAX_SIZE DOCK_MAX_SIZE #define MAINWINDOW_MIN_SIZE (40) #define DRAG_AREA_SIZE (5) #define DRAG_STATE_PROP "DRAG_STATE" using org::kde::StatusNotifierWatcher; // let startdde know that we've already started. void MainWindow::RegisterDdeSession() { QString envName("DDE_SESSION_PROCESS_COOKIE_ID"); QByteArray cookie = qgetenv(envName.toUtf8().data()); qunsetenv(envName.toUtf8().data()); if (!cookie.isEmpty()) { QDBusPendingReply r = DDBusSender() .interface("com.deepin.SessionManager") .path("/com/deepin/SessionManager") .service("com.deepin.SessionManager") .method("Register") .arg(QString(cookie)) .call(); qDebug() << Q_FUNC_INFO << r.value(); } } MainWindow::MainWindow(QWidget *parent) : DBlurEffectWidget(parent) , m_mainPanel(new MainPanelControl(this)) , m_platformWindowHandle(this) , m_wmHelper(DWindowManagerHelper::instance()) , m_multiScreenWorker(new MultiScreenWorker(this)) , m_menuWorker(new MenuWorker(m_multiScreenWorker->dockInter(), this)) , m_shadowMaskOptimizeTimer(new QTimer(this)) , m_dbusDaemonInterface(QDBusConnection::sessionBus().interface()) , m_sniWatcher(new StatusNotifierWatcher(SNI_WATCHER_SERVICE, SNI_WATCHER_PATH, QDBusConnection::sessionBus(), this)) , m_dragWidget(new DragWidget(this)) , m_launched(false) , m_updateDragAreaTimer(new QTimer(this)) , m_dconfig(DConfig::create("org.deepin.dde.dock", "org.deepin.dde.dock", QString(), this)) { setAttribute(Qt::WA_TranslucentBackground); setAttribute(Qt::WA_X11DoNotAcceptFocus); Qt::WindowFlags flags = Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::Window; //1 确保这两行代码的先后顺序,否则会导致任务栏界面不再置顶 setWindowFlags(windowFlags() | flags | Qt::WindowDoesNotAcceptFocus); if (Utils::IS_WAYLAND_DISPLAY) setWindowFlag(Qt::FramelessWindowHint, false); // 会导致设置圆角为0时无效 if (DGuiApplicationHelper::isXWindowPlatform()) { const auto display = QX11Info::display(); if (!display) { qWarning() << "QX11Info::display() is " << display; } else { //2 确保这两行代码的先后顺序,否则会导致任务栏界面不再置顶 XcbMisc::instance()->set_window_type(xcb_window_t(this->winId()), XcbMisc::Dock); } } setMouseTracking(true); setAcceptDrops(true); DPlatformWindowHandle::enableDXcbForWindow(this, true); m_platformWindowHandle.setEnableBlurWindow(true); m_platformWindowHandle.setTranslucentBackground(true); m_platformWindowHandle.setShadowOffset(QPoint(0, 5)); m_platformWindowHandle.setShadowColor(QColor(0, 0, 0, 0.3 * 255)); m_mainPanel->setDisplayMode(m_multiScreenWorker->displayMode()); initMember(); initSNIHost(); initComponents(); initConnections(); resetDragWindow(); for (auto item : DockItemManager::instance()->itemList()) m_mainPanel->insertItem(-1, item); m_dragWidget->setMouseTracking(true); m_dragWidget->setFocusPolicy(Qt::NoFocus); if (!Utils::IS_WAYLAND_DISPLAY) { if ((Top == m_multiScreenWorker->position()) || (Bottom == m_multiScreenWorker->position())) { m_dragWidget->setCursor(Qt::SizeVerCursor); } else { m_dragWidget->setCursor(Qt::SizeHorCursor); } } } /** * @brief MainWindow::launch * 任务栏初次启动时调用此方法,里面是做了一些初始化操作 */ void MainWindow::launch() { if (!qApp->property("CANSHOW").toBool()) return; m_launched = true; m_multiScreenWorker->initShow(); m_shadowMaskOptimizeTimer->start(); QTimer::singleShot(0, this, [ this ] { bool showDock = true; if (m_dconfig.data()->isValid()) showDock = !m_dconfig.data()->value("alwaysHideDock", false).toBool(); setVisible(showDock); if (!showDock && m_multiScreenWorker->dockInter()) { m_multiScreenWorker->dockInter()->setHideMode(KeepHidden); } }); } /** * @brief MainWindow::callShow * 此方法是被外部进程通过DBus调用的。 * @note 当任务栏以-r参数启动时,其不会显示界面,需要在外部通过DBus调用此接口之后才会显示界面, * 这里是以前为了优化任务栏的启动速度做的处理,当任务栏启动时,此时窗管进程可能还未启动完全, * 部分设置未初始化完等,导致任务栏显示的界面异常,所以留下此接口,被startdde延后调用 */ void MainWindow::callShow() { static bool flag = false; if (flag) { return; } flag = true; qApp->setProperty("CANSHOW", true); launch(); // 预留200ms提供给窗口初始化再通知startdde,不影响启动速度 QTimer::singleShot(200, this, &MainWindow::RegisterDdeSession); } /** * @brief MainWindow::relaodPlugins * 需要重新加载插件时,此接口会被调用,目前是用于任务栏的安全模式退出时调用 */ void MainWindow::relaodPlugins() { if (qApp->property("PLUGINSLOADED").toBool()) { return; } DockItemManager::instance()->startLoadPlugins(); qApp->setProperty("PLUGINSLOADED", true); } /** * @brief MainWindow::mousePressEvent * @param e * @note 右键显示任务栏的菜单 */ void MainWindow::mousePressEvent(QMouseEvent *e) { e->ignore(); if (e->button() == Qt::RightButton) { QTimer::singleShot(10, this, [this]{ QMenu *menu = new QMenu(this); m_menuWorker->showDockSettingsMenu(menu); }); return; } if (Utils::IS_WAYLAND_DISPLAY && m_multiScreenWorker->launcherVisible()) { m_multiScreenWorker->setLauncherVisble(false); } } void MainWindow::keyPressEvent(QKeyEvent *e) { switch (e->key()) { #ifdef QT_DEBUG case Qt::Key_Escape: qApp->quit(); break; #endif default:; } } void MainWindow::enterEvent(QEvent *e) { QWidget::enterEvent(e); if (QApplication::overrideCursor() && QApplication::overrideCursor()->shape() != Qt::ArrowCursor) QApplication::restoreOverrideCursor(); } void MainWindow::mouseMoveEvent(QMouseEvent *e) { Q_UNUSED(e); //重写mouseMoveEvent 解决bug12866 leaveEvent事件失效 } void MainWindow::moveEvent(QMoveEvent *event) { Q_UNUSED(event); if (!qApp->property(DRAG_STATE_PROP).toBool()) m_updateDragAreaTimer->start(); } void MainWindow::resizeEvent(QResizeEvent *event) { if (!qApp->property(DRAG_STATE_PROP).toBool()) m_updateDragAreaTimer->start(); // 任务栏大小、位置、模式改变都会触发resize,发射大小改变信号,供依赖项目更新位置 Q_EMIT panelGeometryChanged(); m_mainPanel->updatePluginsLayout(); m_shadowMaskOptimizeTimer->start(); return DBlurEffectWidget::resizeEvent(event); } void MainWindow::dragEnterEvent(QDragEnterEvent *e) { QWidget::dragEnterEvent(e); } void MainWindow::initMember() { //INFO 这里要大于动画的300ms,否则可能动画过程中这个定时器就被触发了 m_updateDragAreaTimer->setInterval(500); m_updateDragAreaTimer->setSingleShot(true); } /** * @brief MainWindow::initSNIHost * @note 将Dock注册到StatusNotifierWatcher服务上 */ void MainWindow::initSNIHost() { // registor dock as SNI Host on dbus QDBusConnection dbusConn = QDBusConnection::sessionBus(); m_sniHostService = QString("org.kde.StatusNotifierHost-") + QString::number(qApp->applicationPid()); dbusConn.registerService(m_sniHostService); dbusConn.registerObject("/StatusNotifierHost", this); if (m_sniWatcher->isValid()) { m_sniWatcher->RegisterStatusNotifierHost(m_sniHostService); } else { qDebug() << SNI_WATCHER_SERVICE << "SNI watcher daemon is not exist for now!"; } } void MainWindow::initComponents() { m_shadowMaskOptimizeTimer->setSingleShot(true); m_shadowMaskOptimizeTimer->setInterval(100); QTimer::singleShot(1, this, &MainWindow::compositeChanged); themeTypeChanged(DGuiApplicationHelper::instance()->themeType()); if (m_dconfig.data()->isValid()) { connect(m_dconfig.data(), &DConfig::valueChanged, this, [this] (const QString &key) { if (key == "alwaysHideDock") { const bool showDock = !m_dconfig.data()->value(key, false).toBool(); setVisible(showDock); if (!showDock && m_multiScreenWorker->dockInter()) { m_multiScreenWorker->dockInter()->setHideMode(KeepHidden); } } }); } } void MainWindow::compositeChanged() { const bool composite = m_wmHelper->hasComposite(); setComposite(composite); m_shadowMaskOptimizeTimer->start(); } void MainWindow::initConnections() { connect(m_shadowMaskOptimizeTimer, &QTimer::timeout, this, &MainWindow::adjustShadowMask, Qt::QueuedConnection); connect(m_wmHelper, &DWindowManagerHelper::hasCompositeChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); connect(&m_platformWindowHandle, &DPlatformWindowHandle::frameMarginsChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); connect(&m_platformWindowHandle, &DPlatformWindowHandle::windowRadiusChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); 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::trayVisableCountChanged, this, &MainWindow::resizeDockIcon, Qt::QueuedConnection); 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_updateDragAreaTimer, &QTimer::timeout, this, &MainWindow::resetDragWindow); //TODO 后面考虑删除这块,目前还不能删除,调整任务栏高度的时候,任务栏外部区域有变化 connect(m_updateDragAreaTimer, &QTimer::timeout, m_multiScreenWorker, &MultiScreenWorker::onRequestUpdateRegionMonitor); connect(m_dragWidget, &DragWidget::dragPointOffset, this, [ = ] { qApp->setProperty(DRAG_STATE_PROP, true); }); connect(m_dragWidget, &DragWidget::dragFinished, this, [ = ] { qApp->setProperty(DRAG_STATE_PROP, false); m_updateDragAreaTimer->start(); }); connect(m_dragWidget, &DragWidget::dragPointOffset, this, &MainWindow::onMainWindowSizeChanged); connect(m_dragWidget, &DragWidget::dragFinished, this, &MainWindow::resetDragWindow); // 更新拖拽区域 // ---------------------------------------------------------------------------------------------------- connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &MainWindow::themeTypeChanged); connect(m_menuWorker, &MenuWorker::autoHideChanged, m_multiScreenWorker, &MultiScreenWorker::onAutoHideChanged); connect(m_multiScreenWorker, &MultiScreenWorker::opacityChanged, this, &MainWindow::setMaskAlpha, Qt::QueuedConnection); connect(m_multiScreenWorker, &MultiScreenWorker::displayModeChanegd, this, &MainWindow::adjustShadowMask, Qt::QueuedConnection); connect(m_multiScreenWorker, &MultiScreenWorker::requestUpdateDockEntry, DockItemManager::instance(), &DockItemManager::requestUpdateDockItem); // 响应后端触控屏拖拽任务栏高度长按信号 connect(TouchSignalManager::instance(), &TouchSignalManager::middleTouchPress, this, &MainWindow::touchRequestResizeDock); connect(TouchSignalManager::instance(), &TouchSignalManager::touchMove, m_dragWidget, &DragWidget::onTouchMove); connect(m_multiScreenWorker, &MultiScreenWorker::notifyDaemonInterfaceUpdate, m_menuWorker, [this]() { m_menuWorker->onNotifyDaemonInterfaceUpdate(m_multiScreenWorker->dockInter()); }); } /** * @brief MainWindow::getTrayVisableItemCount * 重新获取以下当前托盘区域有多少个可见的图标,并更新图标的大小 */ void MainWindow::resizeDockIcon() { m_mainPanel->resizeDockIcon(); } /** * @brief MainWindow::adjustShadowMask 更新任务栏的圆角大小(时尚模式下才有圆角效果) */ void MainWindow::adjustShadowMask() { if (!m_launched || m_shadowMaskOptimizeTimer->isActive()) return; DStyleHelper dstyle(style()); int radius = 0; if (m_wmHelper->hasComposite() && m_multiScreenWorker->displayMode() == DisplayMode::Fashion) { if (Dtk::Core::DSysInfo::isCommunityEdition()) { // 社区版圆角与专业版不同 DPlatformTheme *theme = DGuiApplicationHelper::instance()->systemTheme(); radius = theme->windowRadius(radius); } else { radius = dstyle.pixelMetric(DStyle::PM_TopLevelWindowRadius); } } m_platformWindowHandle.setWindowRadius(radius); m_mainPanel->updatePluginsLayout(); } void MainWindow::onDbusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner) { Q_UNUSED(oldOwner); if (name == SNI_WATCHER_SERVICE && !newOwner.isEmpty()) { qDebug() << SNI_WATCHER_SERVICE << "SNI watcher daemon started, register dock to watcher as SNI Host"; m_sniWatcher->RegisterStatusNotifierHost(m_sniHostService); } } /** * @brief MainWindow::setEffectEnabled * @param enabled 根据当前系统是否enabled特效来更新任务栏的外观样式 */ void MainWindow::setEffectEnabled(const bool enabled) { setMaskColor(AutoColor); setMaskAlpha(m_multiScreenWorker->opacity()); m_platformWindowHandle.setBorderWidth(enabled ? 1 : 0); } /** * @brief MainWindow::setComposite * @param hasComposite 系统是否支持混成(也就是特效) */ void MainWindow::setComposite(const bool hasComposite) { setEffectEnabled(hasComposite); } /** * @brief MainWindow::resetDragWindow 更新任务栏的拖拽区域 * @note 任务栏远离屏幕的一边是支持拖拽的,由一个不可见的widget提拽支持,当任务栏的geometry发生变化的时候,此拖拽区域也需要更新其自身的geometry */ void MainWindow::resetDragWindow() { switch (m_multiScreenWorker->position()) { case Dock::Top: m_dragWidget->setGeometry(0, height() - DRAG_AREA_SIZE, width(), DRAG_AREA_SIZE); break; case Dock::Bottom: m_dragWidget->setGeometry(0, 0, width(), DRAG_AREA_SIZE); break; case Dock::Left: m_dragWidget->setGeometry(width() - DRAG_AREA_SIZE, 0, DRAG_AREA_SIZE, height()); break; case Dock::Right: m_dragWidget->setGeometry(0, 0, DRAG_AREA_SIZE, height()); break; } QRect rect = m_multiScreenWorker->dockRect(m_multiScreenWorker->deskScreen() , m_multiScreenWorker->position() , HideMode::KeepShowing , m_multiScreenWorker->displayMode()); // 这个时候屏幕有可能是隐藏的,不能直接使用this->width()这种去设置任务栏的高度,而应该保证原值 int dockSize = 0; if (m_multiScreenWorker->position() == Position::Left || m_multiScreenWorker->position() == Position::Right) { dockSize = this->width() == 0 ? rect.width() : this->width(); } else { dockSize = this->height() == 0 ? rect.height() : this->height(); } /** FIX ME * 作用:限制dockSize的值在40~100之间。 * 问题1:如果dockSize为39,会导致dock的mainwindow高度变成99,显示的内容高度却是39。 * 问题2:dockSize的值在这里不应该为39,但在高分屏上开启缩放后,拉高任务栏操作会概率出现。 * 暂时未分析出原因,后面再修改。 */ dockSize = qBound(MAINWINDOW_MIN_SIZE, dockSize, MAINWINDOW_MAX_SIZE); // 通知窗管和后端更新数据 m_multiScreenWorker->updateDaemonDockSize(dockSize); // 1.先更新任务栏高度 m_multiScreenWorker->requestUpdateFrontendGeometry(); // 2.再更新任务栏位置,保证先1再2 m_multiScreenWorker->requestNotifyWindowManager(); m_multiScreenWorker->requestUpdateRegionMonitor(); // 界面发生变化,应更新监控区域 if ((Top == m_multiScreenWorker->position()) || (Bottom == m_multiScreenWorker->position())) { m_dragWidget->setCursor(Qt::SizeVerCursor); } else { m_dragWidget->setCursor(Qt::SizeHorCursor); } } void MainWindow::resizeDock(int offset, bool dragging) { qApp->setProperty(DRAG_STATE_PROP, dragging); // 以任务栏的最小高度区域为参照,通过offset设置其高度或宽度 const QRect &rect = m_multiScreenWorker->getDockShowMinGeometry(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, offset, MAINWINDOW_MAX_SIZE)); } break; case Bottom: { newRect.setX(rect.x()); newRect.setY(rect.y() + rect.height() - qBound(MAINWINDOW_MIN_SIZE, offset, MAINWINDOW_MAX_SIZE)); newRect.setWidth(rect.width()); newRect.setHeight(qBound(MAINWINDOW_MIN_SIZE, offset, MAINWINDOW_MAX_SIZE)); } break; case Left: { newRect.setX(rect.x()); newRect.setY(rect.y()); newRect.setWidth(qBound(MAINWINDOW_MIN_SIZE, offset, MAINWINDOW_MAX_SIZE)); newRect.setHeight(rect.height()); } break; case Right: { newRect.setX(rect.x() + rect.width() - qBound(MAINWINDOW_MIN_SIZE, offset, MAINWINDOW_MAX_SIZE)); newRect.setY(rect.y()); newRect.setWidth(qBound(MAINWINDOW_MIN_SIZE, offset, MAINWINDOW_MAX_SIZE)); newRect.setHeight(rect.height()); } break; } // 更新界面大小 m_mainPanel->setFixedSize(newRect.size()); setFixedSize(newRect.size()); move(newRect.topLeft()); if (!dragging) resetDragWindow(); } /** * @brief MainWindow::onMainWindowSizeChanged 任务栏拖拽过程中会不听调用此方法更新自身大小 * @param offset 拖拽时的坐标偏移量 */ void MainWindow::onMainWindowSizeChanged(QPoint offset) { const QRect &rect = m_multiScreenWorker->dockRect(m_multiScreenWorker->deskScreen() , m_multiScreenWorker->position() , HideMode::KeepShowing, m_multiScreenWorker->displayMode()); 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)); } break; case Bottom: { newRect.setX(rect.x()); newRect.setY(rect.y() + rect.height() - qBound(MAINWINDOW_MIN_SIZE, rect.height() - offset.y(), MAINWINDOW_MAX_SIZE)); newRect.setWidth(rect.width()); newRect.setHeight(qBound(MAINWINDOW_MIN_SIZE, rect.height() - offset.y(), MAINWINDOW_MAX_SIZE)); } break; case Left: { newRect.setX(rect.x()); newRect.setY(rect.y()); newRect.setWidth(qBound(MAINWINDOW_MIN_SIZE, rect.width() + offset.x(), MAINWINDOW_MAX_SIZE)); newRect.setHeight(rect.height()); } break; case Right: { newRect.setX(rect.x() + rect.width() - qBound(MAINWINDOW_MIN_SIZE, rect.width() - offset.x(), MAINWINDOW_MAX_SIZE)); newRect.setY(rect.y()); newRect.setWidth(qBound(MAINWINDOW_MIN_SIZE, rect.width() - offset.x(), MAINWINDOW_MAX_SIZE)); newRect.setHeight(rect.height()); } break; } // 更新界面大小 m_mainPanel->setFixedSize(newRect.size()); setFixedSize(newRect.size()); move(newRect.topLeft()); } /** * @brief MainWindow::themeTypeChanged 系统主题发生变化时,此方法被调用 * @param themeType 当前系统主题 */ void MainWindow::themeTypeChanged(DGuiApplicationHelper::ColorType themeType) { if (m_wmHelper->hasComposite()) { if (themeType == DGuiApplicationHelper::DarkType) m_platformWindowHandle.setBorderColor(QColor(0, 0, 0, 255 * 0.3)); else m_platformWindowHandle.setBorderColor(QColor(QColor::Invalid)); } } /** * @brief MainWindow::touchRequestResizeDock 触屏情况用手指调整任务栏高度或宽度 */ void MainWindow::touchRequestResizeDock() { const QPoint touchPos(QCursor::pos()); QRect dockRect = m_multiScreenWorker->dockRect(m_multiScreenWorker->deskScreen() , m_multiScreenWorker->position() , HideMode::KeepShowing , m_multiScreenWorker->displayMode()); // 隐藏状态返回 if (width() == 0 || height() == 0) { return; } int resizeHeight = Utils::SettingValue("com.deepin.dde.dock.touch", QByteArray(), "resizeHeight", 7).toInt(); QRect touchRect; // 任务栏屏幕 内侧边线 内外resizeHeight距离矩形区域内长按可拖动任务栏高度 switch (m_multiScreenWorker->position()) { case Position::Top: touchRect = QRect(dockRect.x(), dockRect.y() + dockRect.height() - resizeHeight, dockRect.width(), resizeHeight * 2); break; case Position::Bottom: touchRect = QRect(dockRect.x(), dockRect.y() - resizeHeight, dockRect.width(), resizeHeight * 2); break; case Position::Left: touchRect = QRect(dockRect.x() + dockRect.width() - resizeHeight, dockRect.y(), resizeHeight * 2, dockRect.height()); break; case Position::Right: touchRect = QRect(dockRect.x() - resizeHeight, dockRect.y(), resizeHeight * 2, dockRect.height()); break; } if (!touchRect.contains(touchPos)) { return; } qApp->postEvent(m_dragWidget, new QMouseEvent(QEvent::MouseButtonPress, m_dragWidget->mapFromGlobal(touchPos) , QPoint(), touchPos, Qt::LeftButton, Qt::NoButton , Qt::NoModifier, Qt::MouseEventSynthesizedByApplication)); } /** * @brief MainWindow::setGeometry * @param rect 设置任务栏的位置和大小,重写此函数时为了及时发出panelGeometryChanged信号,最终供外部DBus调用方使用 */ void MainWindow::setGeometry(const QRect &rect) { if (rect == this->geometry()) { return; } DBlurEffectWidget::setGeometry(rect); emit panelGeometryChanged(); } /** * @brief 当进入安全模式时,通过此方法发送通知告知用户 */ void MainWindow::sendNotifications() { QStringList actionButton; actionButton << "reload" << tr("Exit Safe Mode"); QVariantMap hints; hints["x-deepin-action-reload"] = QString("dbus-send,--session,--dest=com.deepin.dde.Dock,--print-reply,/com/deepin/dde/Dock,com.deepin.dde.Dock.ReloadPlugins"); // 在进入安全模式时,执行此DBUS耗时25S左右,导致任务栏显示阻塞,所以使用线程调用 QtConcurrent::run(QThreadPool::globalInstance(), [=] { DDBusSender() .service("com.deepin.dde.Notification") .path("/com/deepin/dde/Notification") .interface("com.deepin.dde.Notification") .method(QString("Notify")) .arg(QString("dde-control-center")) // appname .arg(static_cast(0)) // id .arg(QString("preferences-system")) // icon .arg(QString(tr("Dock - Safe Mode"))) // summary .arg(QString(tr("The Dock is in safe mode, please exit to show it properly"))) // content .arg(actionButton) // actions .arg(hints) // hints .arg(15000) // timeout .call(); }); }