dde-dock/frame/window/mainwindow.cpp
Robert 0427e19b72
chore: adapt license and copyright (#680)
Modify project to pass the REUSE check

Log: Modify project to pass the REUSE check
Task: https://pms.uniontech.com/task-view-185215.html
Change-Id: Ie954cf985f16c1a243bfc912aa7458c6e85ce9de
2022-09-06 11:36:55 +08:00

681 lines
26 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 <DStyle>
#include <DPlatformWindowHandle>
#include <DSysInfo>
#include <DPlatformTheme>
#include <DDBusSender>
#include <QDebug>
#include <QEvent>
#include <QResizeEvent>
#include <QScreen>
#include <QGuiApplication>
#include <QX11Info>
#include <QtConcurrent>
#include <qpa/qplatformwindow.h>
#include <X11/X.h>
#include <X11/Xutil.h>
#include <com_deepin_dde_daemon_dock.h>
#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<bool> 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<void (QTimer::*)()>(&QTimer::start));
connect(&m_platformWindowHandle, &DPlatformWindowHandle::frameMarginsChanged, m_shadowMaskOptimizeTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
connect(&m_platformWindowHandle, &DPlatformWindowHandle::windowRadiusChanged, m_shadowMaskOptimizeTimer, static_cast<void (QTimer::*)()>(&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的值在40100之间。
* 问题1如果dockSize为39会导致dock的mainwindow高度变成99显示的内容高度却是39。
* 问题2dockSize的值在这里不应该为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<uint>(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();
});
}