From 1691e7188c0b80659526f31aa371293b145bd3b5 Mon Sep 17 00:00:00 2001 From: donghualin Date: Thu, 25 Aug 2022 19:31:31 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BB=BB=E5=8A=A1=E6=A0=8F=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=BB=93=E6=9E=84=E4=BC=98=E5=8C=96=E8=A7=A3=E8=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原来的TrayManagerWindow的类是放到MainPanelWindow类里面作为它的一部分,导致窗管在显示的时候有很多问题 修改方案: 1、将左右侧区域拆分成两个窗体,让它们继承自相同的基类MainWindowBase。 2、左右区域公共的部分,例如圆角、展示区域、动画获取等,都在基类中实现或者通过接口返回 3、增加WindowManager类,管理所有的界面,WindowManager类无需知道具体子类的指针,只需要根据相应的接口来获取即可 4、所有的界面类在main.cpp中创建,调用WindowManager对象设置 5、拆分MultiScreenWorker类,使MultiScreenWorker类只关心任务栏相关的逻辑,无需关心窗体或界面 Log: 优化任务栏的显示问题 Influence: 打开任务栏,观察时尚模式下圆角,左右侧区域中间是否连接在一起等 Bug: https://pms.uniontech.com/bug-view-137267.html Bug: https://pms.uniontech.com/bug-view-140029.html Bug: https://pms.uniontech.com/bug-view-134527.html Bug: https://pms.uniontech.com/bug-view-146743.html Bug: https://pms.uniontech.com/bug-view-150293.html Change-Id: I4266f6f8c983f61258b92834d93cdacd0221d7de --- frame/accessible/accessible.h | 1 + frame/dbus/dbusdockadaptors.cpp | 29 +- frame/dbus/dbusdockadaptors.h | 7 +- frame/main.cpp | 33 +- frame/util/dockscreen.cpp | 64 ++ frame/util/dockscreen.h | 50 + frame/util/menuworker.cpp | 37 +- frame/util/menuworker.h | 16 +- frame/util/multiscreenworker.cpp | 939 ++---------------- frame/util/multiscreenworker.h | 109 +- frame/window/components/datetimedisplayer.cpp | 37 +- frame/window/components/datetimedisplayer.h | 7 +- frame/window/components/dragwidget.cpp | 125 +++ frame/window/components/dragwidget.h | 57 ++ frame/window/mainpanelcontrol.cpp | 205 ++-- frame/window/mainpanelcontrol.h | 11 +- frame/window/mainwindow.cpp | 671 ++----------- frame/window/mainwindow.h | 176 +--- frame/window/mainwindowbase.cpp | 606 +++++++++++ frame/window/mainwindowbase.h | 118 +++ frame/window/quickpluginwindow.cpp | 9 +- frame/window/quickpluginwindow.h | 3 +- frame/window/systempluginwindow.cpp | 45 +- frame/window/systempluginwindow.h | 5 +- frame/window/tray/tray_gridview.cpp | 40 +- frame/window/tray/tray_gridview.h | 1 + frame/window/traymainwindow.cpp | 163 +++ frame/window/traymainwindow.h | 66 ++ frame/window/traymanagerwindow.cpp | 170 ++-- frame/window/traymanagerwindow.h | 14 +- frame/window/windowmanager.cpp | 810 +++++++++++++++ frame/window/windowmanager.h | 97 ++ interfaces/constants.h | 7 + 33 files changed, 2711 insertions(+), 2017 deletions(-) create mode 100644 frame/util/dockscreen.cpp create mode 100644 frame/util/dockscreen.h create mode 100644 frame/window/components/dragwidget.cpp create mode 100644 frame/window/components/dragwidget.h create mode 100644 frame/window/mainwindowbase.cpp create mode 100644 frame/window/mainwindowbase.h create mode 100644 frame/window/traymainwindow.cpp create mode 100644 frame/window/traymainwindow.h create mode 100644 frame/window/windowmanager.cpp create mode 100644 frame/window/windowmanager.h diff --git a/frame/accessible/accessible.h b/frame/accessible/accessible.h index 790878bc9..082c78771 100644 --- a/frame/accessible/accessible.h +++ b/frame/accessible/accessible.h @@ -5,6 +5,7 @@ #include "desktop_widget.h" #include "tipswidget.h" #include "dockpopupwindow.h" +#include "dragwidget.h" #include "launcheritem.h" #include "appitem.h" diff --git a/frame/dbus/dbusdockadaptors.cpp b/frame/dbus/dbusdockadaptors.cpp index 11d5f1ed2..fe945a10c 100644 --- a/frame/dbus/dbusdockadaptors.cpp +++ b/frame/dbus/dbusdockadaptors.cpp @@ -22,16 +22,19 @@ #include "dbusdockadaptors.h" #include "utils.h" #include "dockitemmanager.h" +#include "windowmanager.h" +#include "proxyplugincontroller.h" #include #include #include -DBusDockAdaptors::DBusDockAdaptors(MainWindow* parent) +DBusDockAdaptors::DBusDockAdaptors(WindowManager* parent) : QDBusAbstractAdaptor(parent) , m_gsettings(Utils::SettingsPtr("com.deepin.dde.dock.mainwindow", QByteArray(), this)) + , m_windowManager(parent) { - connect(parent, &MainWindow::panelGeometryChanged, this, [=] { + connect(parent, &WindowManager::panelGeometryChanged, this, [ = ] { emit DBusDockAdaptors::geometryChanged(geometry()); }); @@ -74,19 +77,23 @@ DBusDockAdaptors::~DBusDockAdaptors() } -MainWindow *DBusDockAdaptors::parent() const -{ - return static_cast(QObject::parent()); -} - void DBusDockAdaptors::callShow() { - return parent()->callShow(); + m_windowManager->callShow(); } void DBusDockAdaptors::ReloadPlugins() { - return parent()->reloadPlugins(); + if (qApp->property("PLUGINSLOADED").toBool()) + return; + + // 发送事件,通知代理来加载插件 + PluginLoadEvent event; + QCoreApplication::sendEvent(qApp, &event); + + qApp->setProperty("PLUGINSLOADED", true); + // 退出安全模式 + qApp->setProperty("safeMode", false); } QStringList DBusDockAdaptors::GetLoadedPlugins() @@ -120,7 +127,7 @@ QStringList DBusDockAdaptors::GetLoadedPlugins() void DBusDockAdaptors::resizeDock(int offset, bool dragging) { - parent()->resizeDock(offset, dragging); + m_windowManager->resizeDock(offset, dragging); } // 返回每个插件的识别Key(所以此值应始终不变),供个性化插件根据key去匹配每个插件对应的图标 @@ -181,7 +188,7 @@ void DBusDockAdaptors::setPluginVisible(const QString &pluginName, bool visible) QRect DBusDockAdaptors::geometry() const { - return parent()->geometry(); + return m_windowManager->geometry(); } bool DBusDockAdaptors::showInPrimary() const diff --git a/frame/dbus/dbusdockadaptors.h b/frame/dbus/dbusdockadaptors.h index cc42331e1..2d0575ce9 100644 --- a/frame/dbus/dbusdockadaptors.h +++ b/frame/dbus/dbusdockadaptors.h @@ -30,6 +30,8 @@ * Adaptor class for interface com.deepin.dde.Dock */ class QGSettings; +class WindowManager; + class DBusDockAdaptors: public QDBusAbstractAdaptor { Q_OBJECT @@ -69,11 +71,9 @@ class DBusDockAdaptors: public QDBusAbstractAdaptor Q_PROPERTY(bool showInPrimary READ showInPrimary WRITE setShowInPrimary NOTIFY showInPrimaryChanged) public: - explicit DBusDockAdaptors(MainWindow *parent); + explicit DBusDockAdaptors(WindowManager *parent); virtual ~DBusDockAdaptors(); - MainWindow *parent() const; - public Q_SLOTS: // METHODS void callShow(); void ReloadPlugins(); @@ -103,6 +103,7 @@ private: private: QGSettings *m_gsettings; + WindowManager *m_windowManager; }; #endif //DBUSDOCKADAPTORS diff --git a/frame/main.cpp b/frame/main.cpp index f8e3530d6..8bf7c4583 100644 --- a/frame/main.cpp +++ b/frame/main.cpp @@ -26,6 +26,8 @@ #include "themeappicon.h" #include "dockitemmanager.h" #include "dockapplication.h" +#include "traymainwindow.h" +#include "windowmanager.h" #include #include @@ -221,30 +223,37 @@ int main(int argc, char *argv[]) // 在qApp中记录当前是否为安全模式,如果为安全模式,则无需加载插件,在退出安全模式下,才正常加载插件 // 此处设置这个属性必须在MainWindow创建之前,因为在mainWindow中会创建加载插件的代理,会在代理中根据这个属性来判断是否需要加载插件 bool isSafeMode = IsSaveMode(); - qApp->setProperty("safeMode", isSafeMode); + bool disablePlugin = parser.isSet(disablePlugOption); + qApp->setProperty("safeMode", (isSafeMode || disablePlugin)); + + MultiScreenWorker multiScreenWorker; + + MainWindow mainWindow(&multiScreenWorker); + TrayMainWindow trayMainWindow(&multiScreenWorker); + + WindowManager windowManager(&multiScreenWorker); + + // 保证添加窗口的先后顺序,先添加的窗口显示在左边,后添加的窗口显示在右边 + windowManager.addWindow(&mainWindow); + windowManager.addWindow(&trayMainWindow); // 注册任务栏的DBus服务 - MainWindow mw; - DBusDockAdaptors adaptor(&mw); - - if(Utils::IS_WAYLAND_DISPLAY) { - mw.setAttribute(Qt::WA_NativeWindow); - mw.windowHandle()->setProperty("_d_dwayland_window-type", "dock"); - } + DBusDockAdaptors adaptor(&windowManager); QDBusConnection::sessionBus().registerService("com.deepin.dde.Dock"); - QDBusConnection::sessionBus().registerObject("/com/deepin/dde/Dock", "com.deepin.dde.Dock", &mw); + QDBusConnection::sessionBus().registerObject("/com/deepin/dde/Dock", "com.deepin.dde.Dock", &windowManager); // 当任务栏以-r参数启动时,设置CANSHOW未false,之后调用launch不显示任务栏 qApp->setProperty("CANSHOW", !parser.isSet(runOption)); - mw.launch(); + windowManager.launch(); + mainWindow.setVisible(true); // 判断是否进入安全模式,是否带有入参 -x - if (!isSafeMode && !parser.isSet(disablePlugOption)) { + if (!isSafeMode && !disablePlugin) { qApp->setProperty("PLUGINSLOADED", true); } else { - mw.sendNotifications(); + windowManager.sendNotifications(); } return app.exec(); diff --git a/frame/util/dockscreen.cpp b/frame/util/dockscreen.cpp new file mode 100644 index 000000000..71d4b9641 --- /dev/null +++ b/frame/util/dockscreen.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 "dockscreen.h" +#include "displaymanager.h" + +DockScreen::DockScreen() + : m_primary(DisplayManager::instance()->primary()) + , m_currentScreen(m_primary) + , m_lastScreen(m_primary) +{ +} + +DockScreen *DockScreen::instance() +{ + static DockScreen instance; + return &instance; +} + +const QString &DockScreen::current() const +{ + return m_currentScreen; +} + +const QString &DockScreen::last() const +{ + return m_lastScreen; +} + +const QString &DockScreen::primary() const +{ + return m_primary; +} + +void DockScreen::updateDockedScreen(const QString &screenName) +{ + m_lastScreen = m_currentScreen; + m_currentScreen = screenName; +} + +void DockScreen::updatePrimary(const QString &primary) +{ + m_primary = primary; + if (m_currentScreen.isEmpty()) { + updateDockedScreen(primary); + } +} diff --git a/frame/util/dockscreen.h b/frame/util/dockscreen.h new file mode 100644 index 000000000..c9f9b24ab --- /dev/null +++ b/frame/util/dockscreen.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 DOCKSCREEN_H +#define DOCKSCREEN_H + +#include + +/** + * @brief The DockScreen class + * 保存任务栏的屏幕信息 + */ +class DockScreen +{ +public: + static DockScreen *instance(); + + const QString ¤t() const; + const QString &last() const; + const QString &primary() const; + void updateDockedScreen(const QString &screenName); + void updatePrimary(const QString &primary); + +private: + explicit DockScreen(); + +private: + QString m_primary; + QString m_currentScreen; + QString m_lastScreen; +}; + +#endif // DOCKSCREEN_H diff --git a/frame/util/menuworker.cpp b/frame/util/menuworker.cpp index 583775480..8678b48b4 100644 --- a/frame/util/menuworker.cpp +++ b/frame/util/menuworker.cpp @@ -32,14 +32,13 @@ #define DIS_INS DisplayManager::instance() -MenuWorker::MenuWorker(DockInter *dockInter,QWidget *parent) +MenuWorker::MenuWorker(QObject *parent) : QObject(parent) - , m_dockInter(dockInter) - , m_autoHide(true) + , m_dockInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this)) { } -QMenu *MenuWorker::createMenu(QMenu *settingsMenu) +void MenuWorker::createMenu(QMenu *settingsMenu) { settingsMenu->setAccessibleName("settingsmenu"); settingsMenu->setTitle("Settings Menu"); @@ -152,8 +151,6 @@ QMenu *MenuWorker::createMenu(QMenu *settingsMenu) } delete menuSettings; - menuSettings = nullptr; - return settingsMenu; } void MenuWorker::onDockSettingsTriggered() @@ -175,31 +172,17 @@ void MenuWorker::onDockSettingsTriggered() #endif } -void MenuWorker::showDockSettingsMenu(QMenu *menu) +void MenuWorker::exec() { // 菜单功能被禁用 - static const QGSettings *setting = Utils::ModuleSettingsPtr("menu", QByteArray(), this); + static const QGSettings *setting = Utils::ModuleSettingsPtr("menu", QByteArray()); if (setting && setting->keys().contains("enable") && !setting->get("enable").toBool()) { return; } - // 菜单将要被打开 - setAutoHide(false); - - menu = createMenu(menu); - menu->exec(QCursor::pos()); - - // 菜单已经关闭 - setAutoHide(true); - delete menu; - menu = nullptr; -} - -void MenuWorker::setAutoHide(const bool autoHide) -{ - if (m_autoHide == autoHide) - return; - - m_autoHide = autoHide; - emit autoHideChanged(m_autoHide); + QMenu menu; + if (Utils::IS_WAYLAND_DISPLAY) + menu.setWindowFlag(Qt::FramelessWindowHint); + createMenu(&menu); + menu.exec(QCursor::pos()); } diff --git a/frame/util/menuworker.h b/frame/util/menuworker.h index f128ed518..f62d47fa7 100644 --- a/frame/util/menuworker.h +++ b/frame/util/menuworker.h @@ -20,11 +20,12 @@ */ #ifndef MENUWORKER_H #define MENUWORKER_H -#include #include "constants.h" #include "dbusutil.h" +#include + class QMenu; class QGSettings; /** @@ -34,25 +35,18 @@ class MenuWorker : public QObject { Q_OBJECT public: - explicit MenuWorker(DockInter *dockInter,QWidget *parent = nullptr); + explicit MenuWorker(QObject *parent = nullptr); - void showDockSettingsMenu(QMenu *menu); - -signals: - void autoHideChanged(const bool autoHide) const; - -public slots: - void setAutoHide(const bool autoHide); + void exec(); private: - QMenu *createMenu(QMenu *settingsMenu); + void createMenu(QMenu *settingsMenu); private slots: void onDockSettingsTriggered(); private: DockInter *m_dockInter; - bool m_autoHide; }; #endif // MENUWORKER_H diff --git a/frame/util/multiscreenworker.cpp b/frame/util/multiscreenworker.cpp index c76540799..a7170b8b9 100644 --- a/frame/util/multiscreenworker.cpp +++ b/frame/util/multiscreenworker.cpp @@ -23,6 +23,12 @@ #include "mainwindow.h" #include "utils.h" #include "displaymanager.h" +#include "traymainwindow.h" +#include "mainwindow.h" +#include "menuworker.h" +#include "windowmanager.h" +#include "dockitemmanager.h" +#include "dockscreen.h" #include #include @@ -33,6 +39,7 @@ #include #include #include +#include #include #include @@ -41,14 +48,13 @@ const QString MonitorsSwitchTime = "monitorsSwitchTime"; const QString OnlyShowPrimary = "onlyShowPrimary"; #define DIS_INS DisplayManager::instance() +#define DOCK_SCREEN DockScreen::instance() // 保证以下数据更新顺序(大环节顺序不要变,内部还有一些小的调整,比如任务栏显示区域更新的时候,里面内容的布局方向可能也要更新...) // Monitor数据->屏幕是否可停靠更新->监视唤醒区域更新,任务栏显示区域更新->拖拽区域更新->通知后端接口,通知窗管 -MultiScreenWorker::MultiScreenWorker(QWidget *parent, DWindowManagerHelper *helper) +MultiScreenWorker::MultiScreenWorker(QObject *parent) : QObject(parent) - , m_parent(parent) - , m_wmHelper(helper) , m_eventInter(new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus(), this)) , m_extralEventInter(new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus(), this)) , m_touchEventInter(new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus(), this)) @@ -56,45 +62,30 @@ MultiScreenWorker::MultiScreenWorker(QWidget *parent, DWindowManagerHelper *help , m_launcherInter(new DBusLuncher("com.deepin.dde.Launcher", "/com/deepin/dde/Launcher", QDBusConnection::sessionBus(), this)) , m_monitorUpdateTimer(new QTimer(this)) , m_delayWakeTimer(new QTimer(this)) - , m_ds(DIS_INS->primary()) + , m_position(Dock::Position::Bottom) + , m_hideMode(Dock::HideMode::KeepShowing) + , m_hideState(Dock::HideState::Show) + , m_displayMode(Dock::DisplayMode::Efficient) , m_state(AutoHide) { - qInfo() << "init dock screen: " << m_ds.current(); - initConnection(); initMembers(); initDockMode(); - initDisplayData(); initUI(); + QMetaObject::invokeMethod(this, &MultiScreenWorker::initDisplayData, Qt::QueuedConnection); } -void MultiScreenWorker::initShow() +MultiScreenWorker::~MultiScreenWorker() { - // 仅在初始化时调用一次 - static bool first = true; - if (!first) - return; - first = false; +} - // 这里是为了在调用时让MainWindow更新界面布局方向 - emit requestUpdateLayout(); - - if (m_hideMode == HideMode::KeepShowing) - displayAnimation(m_ds.current(), AniAction::Show); - 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) - displayAnimation(m_ds.current(), AniAction::Show); - else if (m_hideState == HideState::Hide) - displayAnimation(m_ds.current(), AniAction::Hide); - } +void MultiScreenWorker::updateDaemonDockSize(const int &dockSize) +{ + m_dockInter->setWindowSize(uint(dockSize)); + if (m_displayMode == Dock::DisplayMode::Fashion) + m_dockInter->setWindowSizeFashion(uint(dockSize)); + else + m_dockInter->setWindowSizeEfficient(uint(dockSize)); } /** @@ -112,48 +103,7 @@ void MultiScreenWorker::setStates(RunStates state, bool on) m_state &= ~(type); } -/** - * @brief dockRect - * @param screenName 屏幕名 - * @param pos 任务栏位置 - * @param hideMode 模式 - * @param displayMode 状态 - * @return 按照给定的数据计算出任务栏所在位置 - */ -QRect MultiScreenWorker::dockRect(const QString &screenName, const Position &pos, const HideMode &hideMode, const DisplayMode &displayMode) -{ - if (hideMode == HideMode::KeepShowing || (hideMode == HideMode::SmartHide && m_hideState == HideState::Show)) - return getDockShowGeometry(screenName, pos, displayMode); - - return getDockHideGeometry(screenName, pos, displayMode); -} - -/** - * @brief dockRect - * @param screenName 屏幕名 - * @return 按照当前屏幕的当前属性给出任务栏所在区域 - */ -QRect MultiScreenWorker::dockRect(const QString &screenName) -{ - return dockRect(screenName, m_position, m_hideMode, m_displayMode); -} - -/** - * @brief realDockRect 给出不计算缩放情况的区域信息(和后端接口保持一致) - * @param screenName 屏幕名 - * @param pos 任务栏位置 - * @param hideMode 模式 - * @param displayMode 状态 - * @return - */ -QRect MultiScreenWorker::dockRectWithoutScale(const QString &screenName, const Position &pos, const HideMode &hideMode, const DisplayMode &displayMode) -{ - if (hideMode == HideMode::KeepShowing) - return getDockShowGeometry(screenName, pos, displayMode, true); - return getDockHideGeometry(screenName, pos, displayMode, true); -} - -void MultiScreenWorker::onAutoHideChanged(bool autoHide) +void MultiScreenWorker::onAutoHideChanged(const bool autoHide) { if (testState(AutoHide) != autoHide) setStates(AutoHide, autoHide); @@ -163,19 +113,6 @@ void MultiScreenWorker::onAutoHideChanged(bool autoHide) } } -/** - * @brief updateDaemonDockSize - * @param dockSize 这里的高度是通过qt获取的,不能使用后端的接口数据 - */ -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)); -} - #ifndef USE_AM void MultiScreenWorker::handleDbusSignal(QDBusMessage msg) { @@ -225,67 +162,23 @@ void MultiScreenWorker::onExtralRegionMonitorChanged(int x, int y, const QString return; // FIXME:每次都要重置一下,是因为qt中的QScreen类缺少nameChanged信号,后面会给上游提交patch修复 - m_ds.updateDockedScreen(getValidScreen(position())); + DOCK_SCREEN->updateDockedScreen(getValidScreen(position())); // 鼠标移动到任务栏界面之外,停止计时器(延时2秒改变任务栏所在屏幕) m_delayWakeTimer->stop(); if (m_hideMode == HideMode::KeepShowing || ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Show)) { - displayAnimation(m_ds.current(), AniAction::Show); + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Show); } else if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Hide) { - displayAnimation(m_ds.current(), AniAction::Hide); + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Hide); } } -void MultiScreenWorker::showAniFinished() -{ - QRect rect = dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode); - if (m_displayMode == Dock::DisplayMode::Fashion - && (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom)) { - // 特效模式下且在上下位置,需要先设置高度,因为trayManager - // 里面需要根据顶层窗口的高度来设置显示一行还是两行, - // 此时trayManager的长度就会发送变化,返回的建议值才是正确的尺寸值 - parent()->setFixedHeight(rect.height()); - // 调用更新布局接口来调整trayManager窗口的尺寸 - parent()->panel()->updatePluginsLayout(); - // 重新获取窗口尺寸 - rect = dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode); - } - - parent()->setFixedSize(rect.size()); - parent()->setGeometry(rect); - - parent()->panel()->setFixedSize(rect.size()); - parent()->panel()->move(0, 0); - - emit requestUpdateFrontendGeometry(); - emit requestNotifyWindowManager(); -} - -void MultiScreenWorker::hideAniFinished() -{ - // 提前更新界面布局 - emit requestUpdateLayout(); - - const QRect rect = dockRect(m_ds.current(), m_position, HideMode::KeepHidden, m_displayMode); - parent()->setFixedSize(rect.size()); - parent()->setGeometry(rect); - parent()->panel()->setFixedSize(rect.size()); - parent()->panel()->move(0, 0); - - DockItem::setDockPosition(m_position); - qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position)); - - emit requestUpdateFrontendGeometry(); - emit requestNotifyWindowManager(); -} - void MultiScreenWorker::updateDisplay() { //1、屏幕停靠信息, //2、任务栏当前显示在哪个屏幕也需要更新 - //2、监视任务栏唤醒区域信息, //3、任务栏高度或宽度调整的拖拽区域, //4、通知窗管的任务栏显示区域信息, //5、通知后端的任务栏显示区域信息 @@ -293,12 +186,13 @@ void MultiScreenWorker::updateDisplay() qWarning() << "No Screen Can Display."; return; } + // 更新所在屏幕 resetDockScreen(); // 通知后端 - onRequestUpdateFrontendGeometry(); + Q_EMIT requestUpdateFrontendGeometry(); // 通知窗管 - onRequestNotifyWindowManager(); + Q_EMIT requestNotifyWindowManager(); } void MultiScreenWorker::onWindowSizeChanged(uint value) @@ -308,10 +202,10 @@ void MultiScreenWorker::onWindowSizeChanged(uint value) m_monitorUpdateTimer->start(); } -void MultiScreenWorker::primaryScreenChanged() +void MultiScreenWorker::onPrimaryScreenChanged() { // 先更新主屏信息 - m_ds.updatePrimary(DIS_INS->primary()); + DOCK_SCREEN->updatePrimary(DIS_INS->primary()); // 无效值 if (DIS_INS->screenRawHeight() == 0 || DIS_INS->screenRawWidth() == 0) { @@ -323,41 +217,6 @@ void MultiScreenWorker::primaryScreenChanged() m_monitorUpdateTimer->start(); } -void MultiScreenWorker::updateParentGeometry(const QVariant &value, const Position &pos) -{ - Q_ASSERT_X(value.type() == QVariant::Rect, "", "ERROR OCCURED!"); - - const QRect &rect = value.toRect(); - parent()->setFixedSize(rect.size()); - parent()->setGeometry(rect); - - const int panelSize = ((pos == Position::Top || pos == Position::Bottom) ? parent()->panel()->height() : parent()->panel()->width()); - - switch (pos) { - case Position::Top: { - parent()->panel()->move(0, rect.height() - panelSize); - } - break; - case Position::Left: { - parent()->panel()->move(rect.width() - panelSize, 0); - } - break; - case Position::Bottom: - case Position::Right: { - parent()->panel()->move(0, 0); - } - break; - } -} - -void MultiScreenWorker::updateParentGeometry(const QVariant &value) -{ - if (!testState(ShowAnimationStart) && !testState(HideAnimationStart)) - return; - - updateParentGeometry(value, m_position); -} - void MultiScreenWorker::onPositionChanged(int position) { Position lastPos = m_position; @@ -368,18 +227,15 @@ void MultiScreenWorker::onPositionChanged(int position) #endif m_position = static_cast(position); - // 更新鼠标拖拽样式,在类内部设置到qApp单例上去 - if ((Top == m_position) || (Bottom == m_position)) { - parent()->panel()->setCursor(Qt::SizeVerCursor); - } else { - parent()->panel()->setCursor(Qt::SizeHorCursor); - } - if (m_hideMode == HideMode::KeepHidden || (m_hideMode == HideMode::SmartHide && m_hideState == HideState::Hide)) { // 这种情况切换位置,任务栏不需要显示 - displayAnimation(m_ds.current(), lastPos, AniAction::Hide); + // 参数说明 1 当前屏幕名称 2 改变位置之前的位置,因为需要从之前的位置完成隐藏的动画 + // 3 隐藏动画 4 无需考虑当前鼠标是否在任务栏上,这个参数是通过其他方式隐藏唤醒任务栏的时候考虑鼠标是否在任务栏的位置来决定是否做隐藏动画 + // 默认是false,也就是无需考虑 5 当前动画是否为执行位置改变的动画,如果该值为true,那么在动画执行完成后,WindowManager需要给其管理的 + // 子窗口来更新当前的位置的信息 + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), lastPos, Dock::AniAction::Hide, false, true); // 更新当前屏幕信息,下次显示从目标屏幕显示 - m_ds.updateDockedScreen(getValidScreen(m_position)); + DOCK_SCREEN->updateDockedScreen(getValidScreen(m_position)); // 需要更新frontendWindowRect接口数据,否则会造成HideState属性值不变 emit requestUpdateFrontendGeometry(); } else { @@ -396,25 +252,8 @@ void MultiScreenWorker::onDisplayModeChanged(int displayMode) qInfo() << "display mode change:" << displayMode; m_displayMode = static_cast(displayMode); - parent()->panel()->setDisplayMode(m_displayMode); - DockItem::setDockDisplayMode(m_displayMode); - qApp->setProperty(PROP_DISPLAY_MODE, QVariant::fromValue(displayMode)); - - QRect rect; - if (m_hideMode == HideMode::KeepShowing || (m_hideMode == HideMode::SmartHide && m_hideState == HideState::Show)) { - rect = dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode); - } else { - rect = dockRect(m_ds.current(), m_position, HideMode::KeepHidden, m_displayMode); - } - - parent()->setFixedSize(rect.size()); - parent()->move(rect.topLeft()); - - parent()->panel()->setFixedSize(rect.size()); - parent()->panel()->move(0, 0); - - emit displayModeChanegd(); + emit displayModeChanged(m_displayMode); emit requestUpdateFrontendGeometry(); emit requestNotifyWindowManager(); } @@ -430,9 +269,9 @@ void MultiScreenWorker::onHideModeChanged(int hideMode) if (m_hideMode == HideMode::KeepShowing || ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Show)) { - displayAnimation(m_ds.current(), AniAction::Show); + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Show); } else if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Hide) { - displayAnimation(m_ds.current(), AniAction::Hide); + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Hide); } emit requestUpdateFrontendGeometry(); @@ -450,27 +289,27 @@ void MultiScreenWorker::onHideStateChanged(int state) //TODO 这里是否存在屏幕找不到的问题,m_ds的当前屏幕是否可以做成实时同步的,公用一个指针? //TODO 这里真的有必要加以下代码吗,只是隐藏模式的切换,理论上不需要检查屏幕是否允许任务栏停靠 - QScreen *curScreen = DIS_INS->screen(m_ds.current()); + const QString currentScreen = DOCK_SCREEN->current(); + QScreen *curScreen = DIS_INS->screen(currentScreen); if (!DIS_INS->canDock(curScreen, m_position)) { - m_ds.updateDockedScreen(getValidScreen(m_position)); + DOCK_SCREEN->updateDockedScreen(getValidScreen(m_position)); } qInfo() << "hidestate change:" << m_hideMode << m_hideState; if (m_hideMode == HideMode::KeepShowing || ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Show)) { - displayAnimation(m_ds.current(), AniAction::Show); + Q_EMIT requestPlayAnimation(currentScreen, m_position, Dock::AniAction::Show); } else if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Hide) { - // 如果鼠标正在任务栏要显示的区域,就可以不用隐藏(相当于智能隐藏被唤醒一样) - if (getDockShowGeometry(m_ds.current(), m_position, m_displayMode).contains(QCursor::pos())) - return; - displayAnimation(m_ds.current(), AniAction::Hide); + // 最后一个参数,当任务栏的隐藏状态发生变化的时候(从一直显示变成一直隐藏或者智能隐藏),需要考虑鼠标是否在任务栏上,如果在任务栏上,此时无需执行隐藏动画 + Q_EMIT requestPlayAnimation(currentScreen, m_position, Dock::AniAction::Hide, true); } } void MultiScreenWorker::onOpacityChanged(const double value) { - if (int(m_opacity * 100) == int(value * 100)) return; + if (int(m_opacity * 100) == int(value * 100)) + return; m_opacity = value; @@ -659,7 +498,6 @@ void MultiScreenWorker::onRequestUpdateRegionMonitor() break; } - if (!m_touchRectList.contains(monitorRect)) { m_touchRectList << monitorRect; } @@ -671,31 +509,6 @@ void MultiScreenWorker::onRequestUpdateRegionMonitor() m_touchRegisterKey = m_touchEventInter->RegisterAreas(m_touchRectList, flags); } -void MultiScreenWorker::onRequestUpdateFrontendGeometry() -{ - const QRect rect = dockRectWithoutScale(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode); - - //!!! 向com.deepin.dde.daemon.Dock的SetFrontendWindowRect接口设置区域时,此区域的高度或宽度不能为0,否则会导致其HideState属性循环切换,造成任务栏循环显示或隐藏 - if (rect.width() == 0 || rect.height() == 0) - return; - -#ifdef QT_DEBUG - qDebug() << rect; -#endif - - m_dockInter->SetFrontendWindowRect(int(rect.x()), int(rect.y()), uint(rect.width()), uint(rect.height())); - emit requestUpdateDockEntry(); -} - -void MultiScreenWorker::onRequestUpdateLayout() -{ - parent()->panel()->setFixedSize(dockRect(m_ds.current(), position(), HideMode::KeepShowing, displayMode()).size()); - parent()->panel()->move(0, 0); - parent()->panel()->setDisplayMode(displayMode()); - parent()->panel()->setPositonValue(position()); - parent()->panel()->update(); -} - /** * @brief 判断屏幕是否为复制模式的依据,第一个屏幕的X和Y值是否和其他的屏幕的X和Y值相等 * 对于复制模式,这两个值肯定是相等的,如果不是复制模式,这两个值肯定不等,目前支持双屏 @@ -717,147 +530,17 @@ bool MultiScreenWorker::isCopyMode() return true; } -/** - * @brief 这里用到xcb去设置任务栏的高度,比较特殊,参考_NET_WM_STRUT_PARTIAL属性 - * 在屏幕旋转后,所有参数以控制中心自定义设置里主屏显示的图示为准(旋转不用特殊处理) - */ -void MultiScreenWorker::onRequestNotifyWindowManager() -{ - static QRect lastRect = QRect(); - static int lastScreenWidth = 0; - static int lastScreenHeight = 0; - - /* 在非主屏或非一直显示状态时,清除任务栏区域,不挤占应用 */ - if ((!DIS_INS->isCopyMode() && m_ds.current() != m_ds.primary()) || m_hideMode != HideMode::KeepShowing) { - lastRect = QRect(); - - if (Utils::IS_WAYLAND_DISPLAY) { - QList varList; - varList.append(0);//dock位置 - varList.append(0);//dock高度/宽度 - varList.append(0);//start值 - varList.append(0);//end值 - if (parent()->windowHandle()->handle()) { - QGuiApplication::platformNativeInterface()->setWindowProperty(parent()->windowHandle()->handle(),"_d_dwayland_dockstrut", varList); - } - } else { - const auto display = QX11Info::display(); - if (!display) { - qWarning() << "QX11Info::display() is " << display; - return; - } - - XcbMisc::instance()->clear_strut_partial(xcb_window_t(parent()->winId())); - } - - return; - } - - QRect dockGeometry = getDockShowGeometry(m_ds.current(), m_position, m_displayMode, true); - if (lastRect == dockGeometry - && lastScreenWidth == DIS_INS->screenRawWidth() - && lastScreenHeight == DIS_INS->screenRawHeight()) { - return; - } - - lastRect = dockGeometry; - lastScreenWidth = DIS_INS->screenRawWidth(); - lastScreenHeight = DIS_INS->screenRawHeight(); - qDebug() << "dock real geometry:" << dockGeometry; - qDebug() << "screen width:" << DIS_INS->screenRawWidth() << ", height:" << DIS_INS->screenRawHeight(); - - const qreal &ratio = qApp->devicePixelRatio(); - if (Utils::IS_WAYLAND_DISPLAY) { - QList varList = {0, 0, 0, 0}; - switch (m_position) { - case Position::Top: - varList[0] = 1; - varList[1] = dockGeometry.y() + dockGeometry.height() + WINDOWMARGIN * ratio; - varList[2] = dockGeometry.x(); - varList[3] = dockGeometry.x() + dockGeometry.width(); - break; - case Position::Bottom: - varList[0] = 3; - varList[1] = DIS_INS->screenRawHeight() - dockGeometry.y() + WINDOWMARGIN * ratio; - varList[2] = dockGeometry.x(); - varList[3] = dockGeometry.x() + dockGeometry.width(); - break; - case Position::Left: - varList[0] = 0; - varList[1] = dockGeometry.x() + dockGeometry.width() + WINDOWMARGIN * ratio; - varList[2] = dockGeometry.y(); - varList[3] = dockGeometry.y() + dockGeometry.height(); - break; - case Position::Right: - varList[0] = 2; - varList[1] = DIS_INS->screenRawWidth() - dockGeometry.x() + WINDOWMARGIN * ratio; - varList[2] = dockGeometry.y(); - varList[3] = dockGeometry.y() + dockGeometry.height(); - break; - } - - if (parent()->windowHandle()->handle()) { - QGuiApplication::platformNativeInterface()->setWindowProperty(parent()->windowHandle()->handle(),"_d_dwayland_dockstrut", varList); - } - } else { - XcbMisc::Orientation orientation = XcbMisc::OrientationTop; - double strut = 0; - double strutStart = 0; - double strutEnd = 0; - - switch (m_position) { - case Position::Top: - orientation = XcbMisc::OrientationTop; - strut = dockGeometry.y() + dockGeometry.height(); - strutStart = dockGeometry.x(); - strutEnd = dockGeometry.x() + dockGeometry.width(); - break; - case Position::Bottom: - orientation = XcbMisc::OrientationBottom; - strut = DIS_INS->screenRawHeight() - dockGeometry.y(); - strutStart = dockGeometry.x(); - strutEnd = dockGeometry.x() + dockGeometry.width(); - break; - case Position::Left: - orientation = XcbMisc::OrientationLeft; - strut = dockGeometry.x() + dockGeometry.width(); - strutStart = dockGeometry.y(); - strutEnd = dockGeometry.y() + dockGeometry.height(); - break; - case Position::Right: - orientation = XcbMisc::OrientationRight; - strut = DIS_INS->screenRawWidth() - dockGeometry.x(); - strutStart = dockGeometry.y(); - strutEnd = dockGeometry.y() + dockGeometry.height(); - break; - } - - qDebug() << "set reserved area to xcb:" << strut << strutStart << strutEnd; - - const auto display = QX11Info::display(); - if (!display) { - qWarning() << "QX11Info::display() is " << display; - return; - } - - XcbMisc::instance()->set_strut_partial(static_cast(parent()->winId()), orientation, - static_cast(strut + WINDOWMARGIN * ratio), // 设置窗口与屏幕边缘距离,需要乘缩放 - static_cast(strutStart), // 设置任务栏起点坐标(上下为x,左右为y) - static_cast(strutEnd)); // 设置任务栏终点坐标(上下为x,左右为y) - } -} - void MultiScreenWorker::onRequestUpdatePosition(const Position &fromPos, const Position &toPos) { qInfo() << "request change pos from: " << fromPos << " to: " << toPos; // 更新要切换到的屏幕 - if (!DIS_INS->canDock(DIS_INS->screen(m_ds.current()), m_position)) - m_ds.updateDockedScreen(getValidScreen(m_position)); + if (!DIS_INS->canDock(DIS_INS->screen(DOCK_SCREEN->current()), m_position)) + DOCK_SCREEN->updateDockedScreen(getValidScreen(m_position)); - qInfo() << "update allow screen: " << m_ds.current(); + qInfo() << "update allow screen: " << DOCK_SCREEN->current(); // 无论什么模式,都先显示 - changeDockPosition(m_ds.last(), m_ds.current(), fromPos, toPos); + changeDockPosition(DOCK_SCREEN->last(), DOCK_SCREEN->current(), fromPos, toPos); } void MultiScreenWorker::onRequestUpdateMonitorInfo() @@ -879,55 +562,28 @@ void MultiScreenWorker::onRequestDelayShowDock() // 复制模式.不需要响应切换屏幕 if (DIS_INS->screens().size() == 2 && DIS_INS->screens().first()->geometry() == DIS_INS->screens().last()->geometry()) { qInfo() << "copy mode or merge mode"; - parent()->setFixedSize(dockRect(m_ds.current()).size()); - parent()->setGeometry(dockRect(m_ds.current())); + Q_EMIT requestUpdateDockGeometry(m_hideMode); return; } - m_ds.updateDockedScreen(m_delayScreen); + DOCK_SCREEN->updateDockedScreen(m_delayScreen); // 检查当前屏幕的当前位置是否允许显示,不允许需要更新显示信息(这里应该在函数外部就处理好,不应该走到这里) // 检查边缘是否允许停靠 QScreen *curScreen = DIS_INS->screen(m_delayScreen); if (curScreen && DIS_INS->canDock(curScreen, m_position)) { if (m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) { - displayAnimation(m_ds.current(), AniAction::Show); + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Hide); } else if (m_hideMode == HideMode::KeepShowing) { - changeDockPosition(m_ds.last(), m_ds.current(), m_position, m_position); + changeDockPosition(DOCK_SCREEN->last(), DOCK_SCREEN->current(), m_position, m_position); } } } -void MultiScreenWorker::onChildSizeChanged() -{ - // 如果当前为隐藏,则无需再次设置其尺寸 - if (parent()->height() == 0) - return; - - QSize dockSize = dockRect(m_ds.current(), position(), HideMode::KeepShowing, displayMode()).size(); - parent()->move(dockRect(m_ds.current()).topLeft()); - if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { - parent()->setFixedWidth(dockSize.width()); - parent()->panel()->setFixedWidth(dockSize.width()); - } else { - parent()->setFixedHeight(dockSize.height()); - parent()->panel()->setFixedHeight(dockSize.height()); - } - - parent()->panel()->move(0, 0); - parent()->panel()->update(); -} - -MainWindow *MultiScreenWorker::parent() -{ - return static_cast(m_parent); -} - void MultiScreenWorker::initMembers() { m_monitorUpdateTimer->setInterval(100); m_monitorUpdateTimer->setSingleShot(true); - parent()->panel()->setDockScreen(&m_ds); m_delayWakeTimer->setSingleShot(true); @@ -940,10 +596,8 @@ void MultiScreenWorker::initMembers() void MultiScreenWorker::initConnection() { - connect(qApp, &QApplication::primaryScreenChanged, this, &MultiScreenWorker::primaryScreenChanged); - connect(DIS_INS, &DisplayManager::primaryScreenChanged, this, &MultiScreenWorker::primaryScreenChanged); + connect(DIS_INS, &DisplayManager::primaryScreenChanged, this, &MultiScreenWorker::onPrimaryScreenChanged); connect(DIS_INS, &DisplayManager::screenInfoChanged, this, &MultiScreenWorker::requestUpdateMonitorInfo); - connect(parent()->panel(), &MainPanelControl::requestUpdate, this, &MultiScreenWorker::onChildSizeChanged); connect(m_launcherInter, static_cast(&DBusLuncher::VisibleChanged), this, [ = ](bool value) { setStates(LauncherDisplay, value); }); @@ -960,36 +614,21 @@ void MultiScreenWorker::initConnection() this, SLOT(handleDbusSignal(QDBusMessage))); #endif - connect(this, &MultiScreenWorker::requestUpdateFrontendGeometry, this, &MultiScreenWorker::onRequestUpdateFrontendGeometry); connect(this, &MultiScreenWorker::requestUpdatePosition, this, &MultiScreenWorker::onRequestUpdatePosition); - connect(this, &MultiScreenWorker::requestNotifyWindowManager, this, &MultiScreenWorker::onRequestNotifyWindowManager); connect(this, &MultiScreenWorker::requestUpdateMonitorInfo, this, &MultiScreenWorker::onRequestUpdateMonitorInfo); connect(m_delayWakeTimer, &QTimer::timeout, this, &MultiScreenWorker::onRequestDelayShowDock); - // 更新任务栏内容展示方式 - connect(this, &MultiScreenWorker::requestUpdateLayout, this, &MultiScreenWorker::onRequestUpdateLayout); - // 刷新所有显示的内容,布局,方向,大小,位置等 connect(m_monitorUpdateTimer, &QTimer::timeout, this, &MultiScreenWorker::updateDisplay); } 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(dockInter()->position()); onDisplayModeChanged(dockInter()->displayMode()); onHideModeChanged(dockInter()->hideMode()); - onHideStateChanged(dockInter()->hideState()); onOpacityChanged(m_dockInter->opacity()); - - // 初始化透明度 - QTimer::singleShot(0, this, [ = ] {onOpacityChanged(m_dockInter->opacity());}); } void MultiScreenWorker::initDockMode() @@ -1001,8 +640,6 @@ void MultiScreenWorker::initDockMode() m_displayMode = static_cast(m_dockInter->displayMode()); m_opacity = m_dockInter->opacity(); - parent()->panel()->setDisplayMode(m_displayMode); - DockItem::setDockPosition(m_position); qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position)); DockItem::setDockDisplayMode(m_displayMode); @@ -1033,136 +670,6 @@ void MultiScreenWorker::reInitDisplayData() initDisplayData(); } -/** - * @brief MultiScreenWorker::displayAnimation - * 任务栏显示或隐藏过程的动画。 - * @param screen 任务栏要显示的屏幕 - * @param pos 任务栏显示的位置(上:0,右:1,下:2,左:3) - * @param act 显示(隐藏)任务栏 - * @return void - */ -void MultiScreenWorker::displayAnimation(const QString &screen, const Position &pos, AniAction act) -{ - if (!testState(AutoHide) || qApp->property("DRAG_STATE").toBool() - || testState(ChangePositionAnimationStart) - || testState(HideAnimationStart) - || testState(ShowAnimationStart)) - return; - - QRect mainwindowRect = parent()->geometry(); - QRect dockShowRect = getDockShowGeometry(screen, pos, m_displayMode); - QRect dockHideRect = getDockHideGeometry(screen, pos, m_displayMode); - - /** FIXME - * 在高分屏2.75倍缩放的情况下,parent()->geometry()返回的任务栏高度有问题(实际是40,返回是39) - * 在这里增加判断,当返回值在范围(38,42)开区间内,均认为任务栏显示位置正确,直接返回,不执行动画 - * 也就是在实际值基础上下浮动1像素的误差范围 - * 正常屏幕情况下是没有这个问题的 - */ - switch (act) { - case AniAction::Show: - if (pos == Position::Top || pos == Position::Bottom) { - if (qAbs(dockShowRect.height() - mainwindowRect.height()) <= 1 - && mainwindowRect.contains(dockShowRect.center())) { - emit requestNotifyWindowManager(); - return; - } - } else if (pos == Position::Left || pos == Position::Right) { - if (qAbs(dockShowRect.width() - mainwindowRect.width()) <= 1 - && mainwindowRect.contains(dockShowRect.center())) { - emit requestNotifyWindowManager(); - return; - } - } - break; - case AniAction::Hide: - if (dockHideRect == mainwindowRect) { - emit requestNotifyWindowManager(); - return; - } - break; - } - - QVariantAnimation *ani = new QVariantAnimation(this); - ani->setEasingCurve(QEasingCurve::InOutCubic); - -#ifndef DISABLE_SHOW_ANIMATION - const bool composite = m_wmHelper->hasComposite(); // 判断是否开启特效模式 - const int duration = composite ? ANIMATIONTIME : 0; -#else - const int duration = 0; -#endif - ani->setDuration(duration); - - ani->setStartValue(dockHideRect); - ani->setEndValue(dockShowRect); - - switch (act) { - case AniAction::Show: - ani->setDirection(QAbstractAnimation::Forward); - connect(ani, &QVariantAnimation::finished, this, &MultiScreenWorker::showAniFinished); - connect(this, &MultiScreenWorker::requestStopShowAni, ani, &QVariantAnimation::stop); - break; - - case AniAction::Hide: - ani->setDirection(QAbstractAnimation::Backward); // 隐藏时动画反向走 - connect(ani, &QVariantAnimation::finished, this, &MultiScreenWorker::hideAniFinished); - connect(this, &MultiScreenWorker::requestStopHideAni, ani, &QVariantAnimation::stop); - break; - } - - connect(ani, &QVariantAnimation::valueChanged, this, static_cast(&MultiScreenWorker::updateParentGeometry)); - - connect(ani, &QVariantAnimation::stateChanged, this, [ = ](QAbstractAnimation::State newState, QAbstractAnimation::State oldState) { - // 更新动画是否正在进行的信号值 - switch (act) { - case AniAction::Show: - if (newState == QVariantAnimation::Running && oldState == QVariantAnimation::Stopped) { - if (m_hideMode == HideMode::KeepShowing || duration) - setStates(ShowAnimationStart); - else - setStates(DockIsShowing); - } - if (newState == QVariantAnimation::Stopped && oldState == QVariantAnimation::Running) { - if (m_hideMode == HideMode::KeepShowing || duration) - setStates(ShowAnimationStart, false); - else // 如果不是一直显示的状态,则让其延时修改状态,防止在resetDock的时候重复改变其高度引起任务栏闪烁导致无法唤醒 - QTimer::singleShot(ANIMATIONTIME, [ = ] { setStates(DockIsShowing, false); }); - } - break; - case AniAction::Hide: - if (newState == QVariantAnimation::Running && oldState == QVariantAnimation::Stopped) { - setStates(HideAnimationStart); - } - if (newState == QVariantAnimation::Stopped && oldState == QVariantAnimation::Running) { - setStates(HideAnimationStart, false); - } - break; - } - }); - - parent()->panel()->setFixedSize(dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode).size()); - parent()->panel()->move(0, 0); - - emit requestStopShowAni(); - emit requestStopHideAni(); - emit requestUpdateLayout(); - - ani->start(QVariantAnimation::DeleteWhenStopped); -} - -/** - * @brief MultiScreenWorker::displayAnimation - * 任务栏显示或隐藏过程的动画。 - * @param screen 任务栏要显示的屏幕 - * @param act 显示(隐藏)任务栏 - * @return void - */ -void MultiScreenWorker::displayAnimation(const QString &screen, AniAction act) -{ - return displayAnimation(screen, m_position, act); -} - /** * @brief changeDockPosition 做一个动画操作 * @param fromScreen 上次任务栏所在的屏幕 @@ -1177,101 +684,13 @@ void MultiScreenWorker::changeDockPosition(QString fromScreen, QString toScreen, return; } + // 该动画放到WindowManager中来实现 // 更新屏幕信息 - m_ds.updateDockedScreen(toScreen); + DOCK_SCREEN->updateDockedScreen(toScreen); // TODO: 考虑切换过快的情况,这里需要停止上一次的动画,可增加信号控制,暂时无需要 qInfo() << "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)); - qDebug() << fromScreen << "hide from :" << getDockShowGeometry(fromScreen, fromPos, m_displayMode); - qDebug() << fromScreen << "hide to :" << getDockHideGeometry(fromScreen, fromPos, m_displayMode); - - // 显示 - ani2->setStartValue(getDockHideGeometry(toScreen, toPos, m_displayMode)); - ani2->setEndValue(getDockShowGeometry(toScreen, toPos, m_displayMode)); - qDebug() << toScreen << "show from :" << getDockHideGeometry(toScreen, toPos, m_displayMode); - qDebug() << toScreen << "show to :" << getDockShowGeometry(toScreen, toPos, m_displayMode); - - 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); - } - }); - - connect(ani1, &QVariantAnimation::valueChanged, this, [ = ](const QVariant & value) { - updateParentGeometry(value, fromPos); - }); - - // 显示时固定一下内容大小 - connect(ani2, &QVariantAnimation::stateChanged, this, [ = ](QAbstractAnimation::State newState, QAbstractAnimation::State oldState) { - // 位置发生变化时需要更新位置属性,且要在隐藏动画之后,显示动画之前 - DockItem::setDockPosition(m_position); - qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position)); - - 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, [ = ](const QVariant & value) { - updateParentGeometry(value, toPos); - }); - - // 如果更改了显示位置,在显示之前应该更新一下界面布局方向 - if (fromPos != toPos) - connect(ani1, &QVariantAnimation::finished, this, [ = ] { - const auto display = QX11Info::display(); - if (!display) { - qWarning() << "QX11Info::display() is " << display; - } else { - // 先清除原先的窗管任务栏区域 - //XcbMisc::instance()->clear_strut_partial(xcb_window_t(parent()->winId())); - } - - // 隐藏后需要通知界面更新布局方向 - emit requestUpdateLayout(); - }); - - connect(group, &QVariantAnimation::finished, this, [ = ] { - setStates(ChangePositionAnimationStart, false); - - // 结束之后需要根据确定需要再隐藏 - emit showAniFinished(); - emit requestUpdateFrontendGeometry(); - emit requestNotifyWindowManager(); - }); - - setStates(ChangePositionAnimationStart); - - group->start(QVariantAnimation::DeleteWhenStopped); + Q_EMIT requestChangeDockPosition(fromScreen, toScreen, fromPos, toPos); } /** @@ -1281,10 +700,10 @@ void MultiScreenWorker::changeDockPosition(QString fromScreen, QString toScreen, QString MultiScreenWorker::getValidScreen(const Position &pos) { //TODO 考虑在主屏幕名变化时自动更新,是不是就不需要手动处理了 - m_ds.updatePrimary(DIS_INS->primary()); + DOCK_SCREEN->updatePrimary(DIS_INS->primary()); - if (DIS_INS->canDock(DIS_INS->screen(m_ds.current()), pos)) - return m_ds.current(); + if (DIS_INS->canDock(DIS_INS->screen(DOCK_SCREEN->current()), pos)) + return DOCK_SCREEN->current(); if (DIS_INS->canDock(qApp->primaryScreen(), pos)) return DIS_INS->primary(); @@ -1305,21 +724,12 @@ void MultiScreenWorker::resetDockScreen() if (testState(ChangePositionAnimationStart) || testState(HideAnimationStart) || testState(ShowAnimationStart) - || testState(DockIsShowing) || testState(DockIsDraging)) return; - m_ds.updateDockedScreen(getValidScreen(position())); + DOCK_SCREEN->updateDockedScreen(getValidScreen(position())); // 更新任务栏自身信息 - /** - *注意这里要先对parent()进行setFixedSize,在分辨率切换过程中,setGeometry可能会导致其大小未改变 - */ - QRect currentRect = dockRect(m_ds.current()); - QSize dockSize = currentRect.size(); - parent()->setFixedSize(dockSize); - parent()->setGeometry(currentRect); - parent()->panel()->setFixedSize(dockSize); - parent()->panel()->move(0, 0); + Q_EMIT requestUpdateDockGeometry(m_hideMode); } /** @@ -1471,180 +881,9 @@ void MultiScreenWorker::checkXEventMonitorService() } } -QRect MultiScreenWorker::getDockShowMinGeometry(const QString &screenName, bool withoutScale) -{ - QRect rect; - const double ratio = withoutScale ? 1 : qApp->devicePixelRatio(); - const int margin = static_cast((m_displayMode == DisplayMode::Fashion ? 10 : 0) * (withoutScale ? qApp->devicePixelRatio() : 1)); - const int dockSize = 40; - - for (auto s : DIS_INS->screens()) { - if (s->name() == screenName) { - // 拿到当前显示器缩放之前的分辨率 - QRect screenRect = s->handle()->geometry(); - - switch (m_position) { - case Position::Top: - rect.setX(static_cast(screenRect.x() + margin)); - rect.setY(static_cast(screenRect.y() + margin)); - rect.setWidth(static_cast(screenRect.width() / ratio - 2 * margin)); - rect.setHeight(dockSize); - break; - case Position::Bottom: - rect.setX(static_cast(screenRect.x() + margin)); - rect.setY(static_cast(screenRect.y() + screenRect.height() / ratio - margin - dockSize)); - rect.setWidth(static_cast(screenRect.width() / ratio - 2 * margin)); - rect.setHeight(dockSize); - break; - case Position::Left: - rect.setX(static_cast(screenRect.x() + margin)); - rect.setY(static_cast(screenRect.y() + margin)); - rect.setWidth(dockSize); - rect.setHeight(static_cast(screenRect.height() / ratio - 2 * margin)); - break; - case Position::Right: - rect.setX(static_cast(screenRect.x() + screenRect.width() / ratio - margin - dockSize)); - rect.setY(static_cast(screenRect.y() + margin)); - rect.setWidth(dockSize); - rect.setHeight(static_cast(screenRect.height() / ratio - 2 * margin)); - break; - } - } - } - return rect; -} - -/** - * @brief 获取任务栏显示时的参数。目前多屏情况下缩放保持一致,如果后续缩放规则修改,这里需要重新调整 - * - * @param screenName 当前屏幕名字 - * @param pos 任务栏位置 - * @param displaymode 任务栏显示模式 - * @param withoutScale 是否考虑缩放(true:获取的是真实值; false:获取的是前端认为的值(默认)) - * @return QRect 任务栏参数 - */ -QRect MultiScreenWorker::getDockShowGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode, bool withoutScale) -{ - QRect rect; - const double ratio = withoutScale ? 1 : qApp->devicePixelRatio(); - const int margin = static_cast((displaymode == DisplayMode::Fashion ? 10 : 0) * (withoutScale ? qApp->devicePixelRatio() : 1)); - const int dockSize = static_cast((displaymode == DisplayMode::Fashion ? m_dockInter->windowSizeFashion() : m_dockInter->windowSizeEfficient()) * (withoutScale ? qApp->devicePixelRatio() : 1)); - - for (auto s : DIS_INS->screens()) { - if (s->name() == screenName) { - // 拿到当前显示器缩放之前的分辨率 - QRect screenRect = s->handle()->geometry(); - - switch (pos) { - case Position::Top: { - QSize panelSize = parent()->panel()->suitableSize(screenRect.width(), ratio); - rect.setX(screenRect.x() + (static_cast(screenRect.width() / ratio) - panelSize.width()) / 2); - rect.setY(screenRect.y() + static_cast(margin / ratio)); - rect.setWidth(panelSize.width()); - rect.setHeight(dockSize); - } - break; - case Position::Bottom: { - // 先用设置屏幕尺寸,理论上不应该在此处设置,因为这是在一个get方法里面,后续改成直接获取,在其他地方设置 - QSize panelSize = parent()->panel()->suitableSize(screenRect.width(), ratio); - rect.setX(screenRect.x() + (static_cast(screenRect.width() / ratio) - panelSize.width()) / 2); - rect.setY(screenRect.y() + static_cast(screenRect.height() / ratio - margin - dockSize)); - rect.setWidth(panelSize.width()); - rect.setHeight(dockSize); - } - break; - case Position::Left: { - QSize panelSize = parent()->panel()->suitableSize(screenRect.height(), ratio); - rect.setX(screenRect.x() + margin); - rect.setY((screenRect.y() + static_cast(screenRect.height() / ratio) - panelSize.height()) / 2); - rect.setWidth(dockSize); - rect.setHeight(panelSize.height()); - } - break; - case Position::Right: { - QSize panelSize = parent()->panel()->suitableSize(screenRect.height(), ratio); - rect.setX(screenRect.x() + static_cast(screenRect.width() / ratio - margin - dockSize)); - rect.setY((screenRect.y() + static_cast(screenRect.height() / ratio) - panelSize.height()) / 2); - rect.setWidth(dockSize); - rect.setHeight(panelSize.height()); - } - break; - } - } - } - return rect; -} - -/** - * @brief 获取任务栏隐藏时的参数。目前多屏情况下缩放保持一致,如果后续缩放规则修改,这里需要重新调整 - * - * @param screenName 当前屏幕名字 - * @param pos 任务栏位置 - * @param displaymode 任务栏显示模式 - * @param withoutScale 是否考虑缩放(true:获取的是真实值; false:获取的是前端认为的值(默认)) - * @return QRect 任务栏参数 - */ -QRect MultiScreenWorker::getDockHideGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode, bool withoutScale) -{ - QRect rect; - const double ratio = withoutScale ? 1 : qApp->devicePixelRatio(); - const int margin = static_cast((displaymode == DisplayMode::Fashion ? 10 : 0) * (withoutScale ? qApp->devicePixelRatio() : 1)); - - for (auto s : DIS_INS->screens()) { - if (s->name() == screenName) { - // 拿到当前显示器缩放之前的分辨率 - QRect screenRect = s->handle()->geometry(); - - switch (pos) { - case Position::Top: { - QSize panelSize = parent()->panel()->suitableSize(screenRect.width(), ratio); - rect.setX(screenRect.x() + static_cast((screenRect.width() / ratio - panelSize.width()) / 2)); - rect.setY(screenRect.y() + margin); - rect.setWidth(panelSize.width()); - rect.setHeight(0); - } - break; - case Position::Bottom: { - QSize panelSize = parent()->panel()->suitableSize(screenRect.width(), ratio); - rect.setX(screenRect.x() + static_cast((screenRect.width() / ratio - panelSize.width()) / 2)); - rect.setY(screenRect.y() + static_cast(screenRect.height() / ratio - margin)); - rect.setWidth(panelSize.width()); - rect.setHeight(0); - } - break; - case Position::Left: { - QSize panelSize = parent()->panel()->suitableSize(screenRect.height(), ratio); - rect.setX(screenRect.x() + margin); - rect.setY(screenRect.y() + static_cast(static_cast((screenRect.height() / ratio - panelSize.height()) / 2))); - rect.setWidth(0); - rect.setHeight(panelSize.height()); - } - break; - case Position::Right: - QSize panelSize = parent()->panel()->suitableSize(screenRect.height(), ratio); - rect.setX(screenRect.x() + static_cast(screenRect.width() / ratio - margin)); - rect.setY(screenRect.y() + static_cast(static_cast((screenRect.height() / ratio - panelSize.height()) / 2))); - rect.setWidth(0); - rect.setHeight(panelSize.height()); - break; - } - } - } - return rect; -} - -QScreen *MultiScreenWorker::screenByName(const QString &screenName) -{ - foreach (QScreen *screen, qApp->screens()) { - if (screen->name() == screenName) - return screen; - } - return nullptr; -} - bool MultiScreenWorker::onScreenEdge(const QString &screenName, const QPoint &point) { - QScreen *screen = screenByName(screenName); + QScreen *screen = DIS_INS->screen(screenName); if (screen) { const QRect r { screen->geometry() }; const QRect rect { r.topLeft(), r.size() *screen->devicePixelRatio() }; @@ -1730,27 +969,22 @@ void MultiScreenWorker::onTouchRelease(int type, int x, int y, const QString &ke void MultiScreenWorker::onDelayAutoHideChanged() { switch (m_hideMode) { - case HideMode::KeepHidden: - { - // 这时候鼠标如果在任务栏上,就不能隐藏 - if (!parent()->geometry().contains(QCursor::pos())) - displayAnimation(m_ds.current(), AniAction::Hide); - } + case HideMode::KeepHidden: { + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Hide, true); break; + } case HideMode::SmartHide: { if (m_hideState == HideState::Show) - { - displayAnimation(m_ds.current(), AniAction::Show); - } else if (m_hideState == HideState::Hide) { - displayAnimation(m_ds.current(), AniAction::Hide); - } - } - break; - case HideMode::KeepShowing: - displayAnimation(m_ds.current(), AniAction::Show); + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Show); + else if (m_hideState == HideState::Hide) + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Hide); break; } - + case HideMode::KeepShowing: { + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Show); + break; + } + } } /** @@ -1779,8 +1013,9 @@ void MultiScreenWorker::tryToShowDock(int eventX, int eventY) * 使用screenAtByScaled获取屏幕名时,实际上获取的不一定是当前屏幕 * 举例:点(100,100)不在(0,0,100,100)的屏幕上 */ - if (onScreenEdge(m_ds.current(), QPoint(eventX, eventY))) { - toScreen = m_ds.current(); + const QString ¤tScreen = DOCK_SCREEN->current(); + if (onScreenEdge(currentScreen, QPoint(eventX, eventY))) { + toScreen = currentScreen; } // 过滤重复坐标 @@ -1791,7 +1026,7 @@ void MultiScreenWorker::tryToShowDock(int eventX, int eventY) lastPos = QPoint(eventX, eventY); // 任务栏显示状态,但需要切换屏幕 - if (toScreen != m_ds.current()) { + if (toScreen != currentScreen) { if (!m_delayWakeTimer->isActive()) { m_delayScreen = toScreen; m_delayWakeTimer->start(Utils::SettingValue("com.deepin.dde.dock.mainwindow", "/com/deepin/dde/dock/mainwindow/", MonitorsSwitchTime, 2000).toInt()); @@ -1799,8 +1034,7 @@ void MultiScreenWorker::tryToShowDock(int eventX, int eventY) } else { // 任务栏隐藏状态,但需要显示 if (hideMode() == HideMode::KeepShowing) { - parent()->setFixedSize(dockRect(m_ds.current()).size()); - parent()->setGeometry(dockRect(m_ds.current())); + Q_EMIT requestUpdateDockGeometry(m_hideMode); return; } @@ -1809,11 +1043,8 @@ void MultiScreenWorker::tryToShowDock(int eventX, int eventY) return; } - const QRect boundRect = parent()->visibleRegion().boundingRect(); - qDebug() << "boundRect:" << boundRect; - if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) - && (boundRect.size().isEmpty())) { - displayAnimation(m_ds.current(), AniAction::Show); + if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide)) { + Q_EMIT requestPlayAnimation(currentScreen, m_position, Dock::AniAction::Show); } } } diff --git a/frame/util/multiscreenworker.h b/frame/util/multiscreenworker.h index af9e38eef..f82f77cd0 100644 --- a/frame/util/multiscreenworker.h +++ b/frame/util/multiscreenworker.h @@ -50,6 +50,9 @@ DGUI_USE_NAMESPACE * 任务栏的鼠标唤醒区域或任务栏的大小没更新或者更新时的大小还是按照原来的屏幕信息计算而来的, */ +#define DRAG_AREA_SIZE (5) +#define DOCKSPACE (WINDOWMARGIN * 2) + using XEventMonitor = ::com::deepin::api::XEventMonitor; using DBusLuncher = ::com::deepin::dde::Launcher; @@ -59,46 +62,13 @@ class QWidget; class QTimer; class MainWindow; class QGSettings; - -/** - * @brief The DockScreen class - * 保存任务栏的屏幕信息 - */ -class DockScreen -{ -public: - explicit DockScreen(const QString &primary) - : m_currentScreen(primary) - , m_lastScreen(primary) - , m_primary(primary) - {} - inline const QString ¤t() const {return m_currentScreen;} - inline const QString &last() const {return m_lastScreen;} - inline const QString &primary() const {return m_primary;} - - void updateDockedScreen(const QString &screenName) - { - m_lastScreen = m_currentScreen; - m_currentScreen = screenName; - } - - void updatePrimary(const QString &primary) - { - m_primary = primary; - if (m_currentScreen.isEmpty()) { - updateDockedScreen(primary); - } - } - -private: - QString m_currentScreen; - QString m_lastScreen; - QString m_primary; -}; +class TrayMainWindow; +class MenuWorker; class MultiScreenWorker : public QObject { Q_OBJECT + public: enum Flag { Motion = 1 << 0, @@ -106,11 +76,6 @@ public: Key = 1 << 2 }; - enum AniAction { - Show = 0, - Hide - }; - enum RunState { ShowAnimationStart = 0x1, // 单次显示动画正在运行状态 HideAnimationStart = 0x2, // 单次隐藏动画正在运行状态 @@ -119,8 +84,7 @@ public: MousePress = 0x10, // 当前鼠标是否被按下 TouchPress = 0x20, // 当前触摸屏下是否按下 LauncherDisplay = 0x40, // 启动器是否显示 - DockIsShowing = 0x80, // 任务栏正在显示 - DockIsDraging = 0x100, // 任务栏正在拖拽 + DockIsDraging = 0x80, // 任务栏正在拖拽 // 如果要添加新的状态,可以在上面添加 RunState_Mask = 0xffffffff, @@ -128,48 +92,41 @@ public: typedef QFlags RunStates; - MultiScreenWorker(QWidget *parent, DWindowManagerHelper *helper); - - void initShow(); + explicit MultiScreenWorker(QObject *parent = Q_NULLPTR); + ~MultiScreenWorker() override; DockInter *dockInter() { return m_dockInter; } + void updateDaemonDockSize(const int &dockSize); inline bool testState(RunState state) { return (m_state & state); } void setStates(RunStates state, bool on = true); - inline const QString &lastScreen() { return m_ds.last(); } - inline const QString &deskScreen() { return m_ds.current(); } inline const Position &position() { return m_position; } inline const DisplayMode &displayMode() { return m_displayMode; } inline const HideMode &hideMode() { return m_hideMode; } inline const HideState &hideState() { return m_hideState; } inline quint8 opacity() { return m_opacity * 255; } - QRect dockRect(const QString &screenName, const Position &pos, const HideMode &hideMode, const DisplayMode &displayMode); - QRect dockRect(const QString &screenName); - QRect getDockShowMinGeometry(const QString &screenName, bool withoutScale = false); - signals: void opacityChanged(const quint8 value) const; - void displayModeChanegd(); + void displayModeChanged(const Dock::DisplayMode &); // 更新监视区域 void requestUpdateRegionMonitor(); // 更新监听区域 void requestUpdateFrontendGeometry(); //!!! 给后端的区域不能为是或宽度为0的区域,否则会带来HideState死循环切换的bug void requestNotifyWindowManager(); void requestUpdatePosition(const Position &fromPos, const Position &toPos); - void requestUpdateLayout(); // 界面需要根据任务栏更新布局的方向 - void requestUpdateDragArea(); // 更新拖拽区域 void requestUpdateMonitorInfo(); // 屏幕信息发生变化,需要更新任务栏大小,拖拽区域,所在屏幕,监控区域,通知窗管,通知后端, - void requestStopShowAni(); - void requestStopHideAni(); + // 用来通知WindowManager的信号 + void requestUpdateDockGeometry(const Dock::HideMode &hideMode); + void positionChanged(const Dock::Position &position); - void requestUpdateDockEntry(); + void requestPlayAnimation(const QString &screenName, const Position &position, const Dock::AniAction &animation, bool containMouse = false, bool updatePos = false); + void requestChangeDockPosition(const QString &fromScreen, const QString &toScreen, const Position &fromPos, const Position &toPos); public slots: - void onAutoHideChanged(bool autoHide); - void updateDaemonDockSize(int dockSize); + void onAutoHideChanged(const bool autoHide); void onRequestUpdateRegionMonitor(); #ifndef USE_AM @@ -181,16 +138,10 @@ private slots: void onRegionMonitorChanged(int x, int y, const QString &key); void onExtralRegionMonitorChanged(int x, int y, const QString &key); - // Animation - void showAniFinished(); - void hideAniFinished(); - void updateDisplay(); void onWindowSizeChanged(uint value); - void primaryScreenChanged(); - void updateParentGeometry(const QVariant &value, const Position &pos); - void updateParentGeometry(const QVariant &value); + void onPrimaryScreenChanged(); // 任务栏属性变化 void onPositionChanged(int position); @@ -199,11 +150,6 @@ private slots: void onHideStateChanged(int state); void onOpacityChanged(const double value); - // 通知后端任务栏所在位置 - void onRequestUpdateFrontendGeometry(); - - void onRequestUpdateLayout(); - void onRequestNotifyWindowManager(); void onRequestUpdatePosition(const Position &fromPos, const Position &toPos); void onRequestUpdateMonitorInfo(); void onRequestDelayShowDock(); @@ -214,46 +160,33 @@ private slots: void onDelayAutoHideChanged(); - // 子部件尺寸发生变化 - void onChildSizeChanged(); - private: - MainWindow *parent(); // 初始化数据信息 void initMembers(); void initDockMode(); void initConnection(); void initUI(); + void initDisplayData(); void reInitDisplayData(); - void displayAnimation(const QString &screen, const Position &pos, AniAction act); - void displayAnimation(const QString &screen, AniAction act); - void tryToShowDock(int eventX, int eventY); void changeDockPosition(QString fromScreen, QString toScreen, const Position &fromPos, const Position &toPos); - QString getValidScreen(const Position &pos); void resetDockScreen(); void checkDaemonDockService(); void checkXEventMonitorService(); - QRect dockRectWithoutScale(const QString &screenName, const Position &pos, const HideMode &hideMode, const DisplayMode &displayMode); + QString getValidScreen(const Position &pos); - QRect getDockShowGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode, bool withoutScale = false); - QRect getDockHideGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode, bool withoutScale = false); bool isCursorOut(int x, int y); - QScreen *screenByName(const QString &screenName); bool onScreenEdge(const QString &screenName, const QPoint &point); const QPoint rawXPosition(const QPoint &scaledPos); static bool isCopyMode(); private: - QWidget *m_parent; - DWindowManagerHelper *m_wmHelper; - // monitor screen XEventMonitor *m_eventInter; XEventMonitor *m_extralEventInter; @@ -267,8 +200,6 @@ private: QTimer *m_monitorUpdateTimer; QTimer *m_delayWakeTimer; // sp3需求,切换屏幕显示延时,默认2秒唤起任务栏 - DockScreen m_ds; // 屏幕名称信息 - // 任务栏属性 double m_opacity; Position m_position; diff --git a/frame/window/components/datetimedisplayer.cpp b/frame/window/components/datetimedisplayer.cpp index dc8fe195b..88c022944 100644 --- a/frame/window/components/datetimedisplayer.cpp +++ b/frame/window/components/datetimedisplayer.cpp @@ -122,10 +122,15 @@ void DateTimeDisplayer::updatePolicy() } } -QSize DateTimeDisplayer::suitableSize() +QSize DateTimeDisplayer::suitableSize() const { - DateTimeInfo info = dateTimeInfo(); - if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + return suitableSize(m_position); +} + +QSize DateTimeDisplayer::suitableSize(const Dock::Position &position) const +{ + DateTimeInfo info = dateTimeInfo(position); + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { int width = info.m_timeRect.width() + info.m_dateRect.width() + 16; return QSize(width, height()); } @@ -151,7 +156,7 @@ void DateTimeDisplayer::mouseReleaseEvent(QMouseEvent *event) .method("Toggle").call(); } -QString DateTimeDisplayer::getTimeString() const +QString DateTimeDisplayer::getTimeString(const Dock::Position &position) const { QString tFormat = QString("hh:mm"); int type = m_timedateInter->shortTimeFormat(); @@ -159,7 +164,7 @@ QString DateTimeDisplayer::getTimeString() const tFormat = timeFormat[type]; if (!m_timedateInter->use24HourFormat()) { - if (m_position == Dock::Top || m_position == Dock::Bottom) + if (position == Dock::Top || position == Dock::Bottom) tFormat = tFormat.append(" AP"); else tFormat = tFormat.append("\nAP"); @@ -169,13 +174,18 @@ QString DateTimeDisplayer::getTimeString() const } QString DateTimeDisplayer::getDateString() const +{ + return getDateString(m_position); +} + +QString DateTimeDisplayer::getDateString(const Dock::Position &position) const { int type = m_timedateInter->shortDateFormat(); QString shortDateFormat = "yyyy-MM-dd"; if (dateFormat.contains(type)) shortDateFormat = dateFormat.value(type); // 如果是左右方向,则不显示年份 - if (m_position == Dock::Position::Left || m_position == Dock::Position::Right) { + if (position == Dock::Position::Left || position == Dock::Position::Right) { static QStringList yearStrList{"yyyy/", "yyyy-", "yyyy.", "yy/", "yy-", "yy."}; for (int i = 0; i < yearStrList.size() ; i++) { const QString &yearStr = yearStrList[i]; @@ -189,16 +199,16 @@ QString DateTimeDisplayer::getDateString() const return QDateTime::currentDateTime().toString(shortDateFormat); } -DateTimeDisplayer::DateTimeInfo DateTimeDisplayer::dateTimeInfo() +DateTimeDisplayer::DateTimeInfo DateTimeDisplayer::dateTimeInfo(const Dock::Position &position) const { DateTimeInfo info; info.m_timeRect = rect(); info.m_dateRect = rect(); - info.m_time = getTimeString(); - info.m_date = getDateString(); + info.m_time = getTimeString(position); + info.m_date = getDateString(position); - if (m_position == Dock::Top || m_position == Dock::Bottom) { + if (position == Dock::Top || position == Dock::Bottom) { int timeWidth = QFontMetrics(timeFont()).boundingRect(info.m_time).width() + 3; int dateWidth = QFontMetrics(m_dateFont).boundingRect(info.m_date).width() + 2; info.m_timeRect = QRect(ITEMSPACE, 0, timeWidth, height()); @@ -243,7 +253,7 @@ void DateTimeDisplayer::paintEvent(QPaintEvent *e) { Q_UNUSED(e); - DateTimeInfo info = dateTimeInfo(); + DateTimeInfo info = dateTimeInfo(m_position); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); @@ -383,3 +393,8 @@ void DateTimeDisplayer::updateLastData(const DateTimeInfo &info) else m_currentSize = dateTimeSize.height(); } + +QString DateTimeDisplayer::getTimeString() const +{ + return getTimeString(m_position); +} diff --git a/frame/window/components/datetimedisplayer.h b/frame/window/components/datetimedisplayer.h index 693db0b53..2c933c07d 100644 --- a/frame/window/components/datetimedisplayer.h +++ b/frame/window/components/datetimedisplayer.h @@ -52,7 +52,8 @@ public: ~DateTimeDisplayer() override; void setPositon(Dock::Position position); void setOneRow(bool oneRow); - QSize suitableSize(); + QSize suitableSize() const; + QSize suitableSize(const Dock::Position &position) const; Q_SIGNALS: void requestUpdate(); // 当日期时间格式发生变化的时候,需要通知外面来更新窗口尺寸 @@ -67,11 +68,13 @@ protected: private: void updatePolicy(); - DateTimeInfo dateTimeInfo(); + DateTimeInfo dateTimeInfo(const Dock::Position &position) const; void updateLastData(const DateTimeInfo &info); QString getTimeString() const; + QString getTimeString(const Dock::Position &position) const; QString getDateString() const; + QString getDateString(const Dock::Position &position) const; QPoint tipsPoint() const; QFont timeFont() const; diff --git a/frame/window/components/dragwidget.cpp b/frame/window/components/dragwidget.cpp new file mode 100644 index 000000000..38aef59c9 --- /dev/null +++ b/frame/window/components/dragwidget.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 "dragwidget.h" +#include "utils.h" +#include "constants.h" + +#include +#include + +DragWidget::DragWidget(QWidget *parent) + : QWidget(parent) + , m_dragStatus(false) +{ + setObjectName("DragWidget"); +} + +bool DragWidget::isDraging() const +{ + return m_dragStatus; +} + +void DragWidget::onTouchMove(double scaleX, double scaleY) +{ + Q_UNUSED(scaleX); + Q_UNUSED(scaleY); + + static QPoint lastPos; + QPoint curPos = QCursor::pos(); + if (lastPos == curPos) { + return; + } + lastPos = curPos; + qApp->postEvent(this, new QMouseEvent(QEvent::MouseMove, mapFromGlobal(curPos) + , QPoint(), curPos, Qt::LeftButton, Qt::LeftButton + , Qt::NoModifier, Qt::MouseEventSynthesizedByApplication)); +} + +void DragWidget::mousePressEvent(QMouseEvent *event) +{ + // qt转发的触屏按下信号不进行响应 + if (event->source() == Qt::MouseEventSynthesizedByQt) + return; + + if (event->button() == Qt::LeftButton) { + m_resizePoint = event->globalPos(); + m_dragStatus = true; + this->grabMouse(); + } +} + +void DragWidget::mouseMoveEvent(QMouseEvent *) +{ + if (m_dragStatus) { + QPoint offset = QPoint(QCursor::pos() - m_resizePoint); + emit dragPointOffset(offset); + } +} + +void DragWidget::mouseReleaseEvent(QMouseEvent *) +{ + if (!m_dragStatus) + return; + + m_dragStatus = false; + releaseMouse(); + emit dragFinished(); +} + +void DragWidget::enterEvent(QEvent *) +{ + if (Utils::IS_WAYLAND_DISPLAY) + updateCursor(); + else + QApplication::setOverrideCursor(cursor()); +} + +void DragWidget::leaveEvent(QEvent *) +{ + QApplication::setOverrideCursor(Qt::ArrowCursor); +} + +void DragWidget::updateCursor() +{ + QString theme = Utils::SettingValue("com.deepin.xsettings", "/com/deepin/xsettings/", "gtk-cursor-theme-name", "bloom").toString(); + int cursorSize = Utils::SettingValue("com.deepin.xsettings", "/com/deepin/xsettings/", "gtk-cursor-theme-size", 24).toInt(); + Dock::Position position = static_cast(qApp->property("position").toInt()); + + static QString lastTheme; + static int lastPosition = -1; + static int lastCursorSize = -1; + if (theme != lastTheme || position != lastPosition || cursorSize != lastCursorSize) { + lastTheme = theme; + lastPosition = position; + lastCursorSize = cursorSize; + const char* cursorName = (position == Dock::Position::Bottom || position == Dock::Position::Top) ? "v_double_arrow" : "h_double_arrow"; + QCursor *newCursor = ImageUtil::loadQCursorFromX11Cursor(theme.toStdString().c_str(), cursorName, cursorSize); + if (!newCursor) + return; + + setCursor(*newCursor); + static QCursor *lastCursor = nullptr; + if (lastCursor) + delete lastCursor; + + lastCursor = newCursor; + } +} diff --git a/frame/window/components/dragwidget.h b/frame/window/components/dragwidget.h new file mode 100644 index 000000000..d19f9a2af --- /dev/null +++ b/frame/window/components/dragwidget.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 DRAGWIDGET_H +#define DRAGWIDGET_H + +#include + +class DragWidget : public QWidget +{ + Q_OBJECT + +public: + explicit DragWidget(QWidget *parent = nullptr); + + bool isDraging() const; + +public Q_SLOTS: + void onTouchMove(double scaleX, double scaleY); + +Q_SIGNALS: + void dragPointOffset(QPoint); + void dragFinished(); + +protected: + void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *) override; + void mouseReleaseEvent(QMouseEvent *) override; + void enterEvent(QEvent *) override; + void leaveEvent(QEvent *) override; + +private: + void updateCursor(); + +private: + bool m_dragStatus; + QPoint m_resizePoint; +}; + +#endif // DRAGWIDGET_H diff --git a/frame/window/mainpanelcontrol.cpp b/frame/window/mainpanelcontrol.cpp index 495e75a67..8548449d1 100755 --- a/frame/window/mainpanelcontrol.cpp +++ b/frame/window/mainpanelcontrol.cpp @@ -31,7 +31,6 @@ #include "utils.h" #include "desktop_widget.h" #include "imageutil.h" -#include "traymanagerwindow.h" #include "multiscreenworker.h" #include "displaymanager.h" #include "recentapphelper.h" @@ -39,7 +38,7 @@ #include "multiwindowhelper.h" #include "mainwindow.h" #include "appmultiitem.h" -#include "multiwindowhelper.h" +#include "dockscreen.h" #include #include @@ -66,16 +65,10 @@ #define PLUGIN_MAX_SIZE 40 #define PLUGIN_MIN_SIZE 20 #define DESKTOP_SIZE 10 -// 任务栏圆角最小的时候,任务栏的高度值 -#define MINRADIUSSIZE 46 -// 任务栏圆角最小值和最大值的差值 -#define MAXDIFFVALUE 6 -// 最小圆角值 -#define MINRADIUS 12 DWIDGET_USE_NAMESPACE -MainPanelControl::MainPanelControl(QWidget *parent) +MainPanelControl::MainPanelControl(DockInter *dockInter, QWidget *parent) : QWidget(parent) , m_mainPanelLayout(new QBoxLayout(QBoxLayout::LeftToRight, this)) , m_fixedAreaWidget(new QWidget(this)) @@ -98,7 +91,6 @@ MainPanelControl::MainPanelControl(QWidget *parent) , m_multiWindowLayout(new QBoxLayout(QBoxLayout::LeftToRight, m_multiWindowWidget)) , m_toolSonAreaWidget(new QWidget(m_toolAreaWidget)) , m_toolSonLayout(new QBoxLayout(QBoxLayout::LeftToRight, m_toolSonAreaWidget)) - , m_trayManagerWidget(new TrayManagerWindow(this)) , m_pluginLayout(new QBoxLayout(QBoxLayout::LeftToRight, this)) , m_desktopWidget(new DesktopWidget(this)) , m_position(Position::Bottom) @@ -106,10 +98,9 @@ MainPanelControl::MainPanelControl(QWidget *parent) , m_appDragWidget(nullptr) , m_displayMode(Efficient) , m_tray(nullptr) - , m_dockScreen(nullptr) - , m_dockInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this)) + , m_dockInter(dockInter) , m_recentHelper(new RecentAppHelper(m_appAreaSonWidget, m_recentAreaWidget, m_dockInter, this)) - , m_toolHelper(new ToolAppHelper(m_pluginAreaWidget, m_toolAreaWidget, this)) + , m_toolHelper(new ToolAppHelper(m_pluginAreaWidget, m_toolSonAreaWidget, this)) , m_multiHelper(new MultiWindowHelper(m_appAreaSonWidget, m_multiWindowWidget, this)) { initUI(); @@ -161,6 +152,7 @@ void MainPanelControl::initUI() m_recentAreaWidget->setLayout(m_recentLayout); m_recentLayout->setSpacing(0); m_recentLayout->setContentsMargins(0, 0, 0, 0); + m_recentLayout->setAlignment(Qt::AlignCenter); m_mainPanelLayout->addWidget(m_recentAreaWidget); m_recentSpliter->setObjectName("spliter_recent"); @@ -206,10 +198,6 @@ void MainPanelControl::initUI() m_pluginLayout->setContentsMargins(0, 0, 0, 0); m_mainPanelLayout->addWidget(m_pluginAreaWidget, 0, Qt::AlignCenter); - /* 时尚模式下右侧的插件区域 */ - m_mainPanelLayout->addSpacing(15); - m_mainPanelLayout->addWidget(m_trayManagerWidget); - /* 桌面预览 */ m_desktopWidget->setObjectName("showdesktoparea"); m_mainPanelLayout->addWidget(m_desktopWidget); @@ -224,7 +212,6 @@ void MainPanelControl::initUI() void MainPanelControl::initConnection() { - connect(m_trayManagerWidget, &TrayManagerWindow::requestUpdate, this, &MainPanelControl::onRequestUpdate); connect(m_recentHelper, &RecentAppHelper::requestUpdate, this, &MainPanelControl::requestUpdate); connect(m_recentHelper, &RecentAppHelper::recentVisibleChanged, this, &MainPanelControl::onRecentVisibleChanged); connect(m_recentHelper, &RecentAppHelper::dockAppVisibleChanged, this, &MainPanelControl::onDockAppVisibleChanged); @@ -261,13 +248,15 @@ void MainPanelControl::updateMainPanelLayout() m_appAreaWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_pluginAreaWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_trayAreaWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); - m_trayManagerWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); m_mainPanelLayout->setDirection(QBoxLayout::LeftToRight); m_fixedAreaLayout->setDirection(QBoxLayout::LeftToRight); m_pluginLayout->setDirection(QBoxLayout::LeftToRight); m_trayAreaLayout->setDirection(QBoxLayout::LeftToRight); m_appAreaSonLayout->setDirection(QBoxLayout::LeftToRight); m_recentLayout->setDirection(QBoxLayout::LeftToRight); + m_multiWindowLayout->setDirection(QBoxLayout::LeftToRight); + m_toolAreaLayout->setDirection(QBoxLayout::LeftToRight); + m_toolSonLayout->setDirection(QBoxLayout::LeftToRight); m_trayAreaLayout->setContentsMargins(0, 10, 0, 10); m_pluginLayout->setContentsMargins(10, 0, 10, 0); m_multiWindowLayout->setContentsMargins(0, 2, 0, 2); @@ -278,13 +267,15 @@ void MainPanelControl::updateMainPanelLayout() m_appAreaWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_pluginAreaWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_trayAreaWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - m_trayManagerWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_mainPanelLayout->setDirection(QBoxLayout::TopToBottom); m_fixedAreaLayout->setDirection(QBoxLayout::TopToBottom); m_pluginLayout->setDirection(QBoxLayout::TopToBottom); m_trayAreaLayout->setDirection(QBoxLayout::TopToBottom); m_appAreaSonLayout->setDirection(QBoxLayout::TopToBottom); m_recentLayout->setDirection(QBoxLayout::TopToBottom); + m_multiWindowLayout->setDirection(QBoxLayout::TopToBottom); + m_toolAreaLayout->setDirection(QBoxLayout::TopToBottom); + m_toolSonLayout->setDirection(QBoxLayout::TopToBottom); m_trayAreaLayout->setContentsMargins(10, 0, 10, 0); m_pluginLayout->setContentsMargins(0, 10, 0, 10); m_multiWindowLayout->setContentsMargins(2, 0, 2, 0); @@ -364,14 +355,6 @@ void MainPanelControl::resizeEvent(QResizeEvent *event) QWidget::resizeEvent(event); resizeDesktopWidget(); resizeDockIcon(); - resetRadius(); -} - -void MainPanelControl::resetRadius() -{ - int size = ((m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) ? height() : width()); - int radius = qMin(MAXDIFFVALUE, qMax(size - MINRADIUSSIZE, 0)) + MINRADIUS; - qApp->setProperty("EffectBorderRadius", radius); } /** 当用户从最近使用区域拖动应用到左侧应用区域的时候,将该应用驻留 @@ -407,12 +390,10 @@ void MainPanelControl::updateAppAreaSonWidgetSize() m_appAreaSonWidget->setMaximumHeight(height()); m_appAreaSonWidget->setMaximumWidth(m_appAreaWidget->width()); m_recentAreaWidget->setFixedHeight(height()); - //m_toolAreaWidget->setFixedHeight(height()); } else { m_appAreaSonWidget->setMaximumWidth(width()); m_appAreaSonWidget->setMaximumHeight(m_appAreaWidget->height()); m_recentAreaWidget->setFixedWidth(width()); - //m_toolAreaWidget->setFixedWidth(width()); } m_appAreaSonWidget->adjustSize(); @@ -429,10 +410,7 @@ void MainPanelControl::setPositonValue(Dock::Position position) return; m_position = position; - QMetaObject::invokeMethod(this, [ this ] { - m_trayManagerWidget->setPositon(m_position); - updateMainPanelLayout(); - }, Qt::QueuedConnection); + QMetaObject::invokeMethod(this, &MainPanelControl::updateMainPanelLayout, Qt::QueuedConnection); } /**向任务栏插入各类应用,并将属于同一个应用的窗口合并到同一个应用图标 @@ -903,7 +881,6 @@ void MainPanelControl::startDrag(DockItem *dockItem) if (item->itemType() == DockItem::App) { // 判断是否在回收站区域, 如果在回收站区域,则移除驻留 - PluginsItem *trashItem = m_toolHelper->trashPlugin(); if (!trashItem) return; @@ -1060,49 +1037,9 @@ void MainPanelControl::updatePluginsLayout() } } } - m_trayManagerWidget->updateLayout(); } -void MainPanelControl::setDockScreen(DockScreen *dockScreen) -{ - m_dockScreen = dockScreen; -} - -QPainterPath MainPanelControl::areaPath() -{ - if (m_displayMode == DisplayMode::Efficient) - return QPainterPath(); - - int radius = qApp->property("EffectBorderRadius").toInt(); - QPainterPath path; - if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { - int leftWidth = m_fixedAreaWidget->width() + m_fixedSpliter->width() + m_appAreaWidget->width(); - if (m_recentLayout->count() > 0) - leftWidth += m_recentAreaWidget->width(); - - if (m_toolAreaLayout->count() > 0) - leftWidth += m_toolAreaWidget->width(); - - int roundHeight = height(); - path.addRoundedRect(QRect(0, 0, leftWidth, roundHeight), radius, radius); - path.addRoundedRect(QRect(m_trayManagerWidget->x(), 0, m_trayManagerWidget->width(), roundHeight), radius, radius); - } else { - int roundWidth = width(); - int topHeight = m_fixedAreaWidget->height() + m_fixedSpliter->height() + m_appAreaWidget->height(); - if (m_recentLayout->count() > 0) - topHeight += m_recentAreaWidget->height(); - - if (m_toolAreaLayout->count() > 0) - topHeight += m_toolAreaWidget->height(); - - path.addRoundedRect(QRect(0, 0, roundWidth, topHeight), radius, radius); - path.addRoundedRect(QRect(0, m_trayManagerWidget->y(), roundWidth, m_trayManagerWidget->height()), radius, radius); - } - - return path; -} - -QSize MainPanelControl::suitableSize(int screenSize, double deviceRatio) const +QSize MainPanelControl::suitableSize(const Position &position, int screenSize, double deviceRatio) const { if (screenSize <= 0) return QSize(-1, -1); @@ -1111,60 +1048,85 @@ QSize MainPanelControl::suitableSize(int screenSize, double deviceRatio) const if (ratio <= 0) ratio = qApp->devicePixelRatio(); + int dockSize = ((position == Position::Top || position == Position::Bottom) ? height() : width()); + // 如果实际的尺寸超过了任务栏允许的最大尺寸,此时可能是在发生位置变换,这个时候使用接口获取的尺寸即可 + // 如果任务栏在隐藏状态,那么此时获取到的高度为0,此时从后端获取任务栏的实际高度 + HideState hideState = static_cast(qApp->property(PROP_HIDE_STATE).toInt()); + if (dockSize > DOCK_MAX_SIZE || hideState == HideState::Hide) + dockSize = static_cast((m_displayMode == DisplayMode::Efficient ? m_dockInter->windowSizeEfficient() : m_dockInter->windowSizeFashion()) * qApp->devicePixelRatio()); + if (m_displayMode == DisplayMode::Efficient) { // 如果是高效模式 - if (m_position == Position::Top || m_position == Position::Bottom) - return QSize(static_cast(screenSize / ratio), height()); + if (position == Position::Top || position == Position::Bottom) + return QSize(static_cast(screenSize / ratio), dockSize); - return QSize(width(), static_cast(screenSize / ratio)); + return QSize(dockSize, static_cast(screenSize / ratio)); } - QSize traySuitableSize = m_trayManagerWidget->suitableSize(); // 如果是特效模式 int totalLength = static_cast(screenSize / ratio); - // 减去右侧托盘和快捷设置还有插件区域的尺寸 - totalLength -= (((m_position == Position::Top || m_position == Position::Bottom) ? traySuitableSize.width() : traySuitableSize.height()) / ratio); // 需要参与计算的图标的总数 - int iconCount = m_fixedAreaLayout->count() + m_appAreaSonLayout->count() + m_recentLayout->count() + m_toolAreaLayout->count(); - if (iconCount <= 0) { - if (m_position == Position::Top || m_position == Position::Bottom) - return QSize((static_cast((traySuitableSize.width() + 20) / ratio)), height()); + int iconCount = m_fixedAreaLayout->count() + m_appAreaSonLayout->count() + m_recentLayout->count() + m_toolSonLayout->count(); + int multiWindowCount = m_multiWindowLayout->count(); + if (iconCount <= 0 && multiWindowCount <= 0) { + if (position == Position::Top || position == Position::Bottom) + return QSize((static_cast(dockSize / ratio)), dockSize); - return QSize(width(), static_cast((traySuitableSize.height() + 20) / ratio)); + return QSize(dockSize, static_cast(dockSize / ratio)); } - int redundantLength = (totalLength % iconCount); // icon宽度 = (总宽度-余数)/icon个数 - int iconSize = (totalLength - redundantLength) / iconCount; + int iconSize = qMin(((totalLength - redundantLength) / iconCount), dockSize); - if (m_position == Position::Top || m_position == Position::Bottom) { - iconSize = qMin(iconSize, height()); - int spliterWidth = m_fixedSpliter->isVisible() ? m_fixedSpliter->width() : 0; + if (position == Position::Top || position == Position::Bottom) { + int spliterWidth = m_fixedSpliter->isVisible() ? SPLITER_SIZE : 0; if (m_appSpliter->isVisible()) - spliterWidth += m_appSpliter->width(); + spliterWidth += SPLITER_SIZE; if (m_recentSpliter->isVisible()) - spliterWidth += m_recentSpliter->isVisible(); + spliterWidth += SPLITER_SIZE; - int panelWidth = qMin(iconSize * iconCount + static_cast((spliterWidth + traySuitableSize.width() + 20) / ratio), - static_cast(screenSize / deviceRatio)); + int multiSize = 0; + // 计算每个多开窗口的尺寸 + if (multiWindowCount > 0) { + for (int i = 0; i < multiWindowCount; i++) { + AppMultiItem *multiItem = qobject_cast(m_multiWindowLayout->itemAt(i)->widget()); + if (!multiItem) + continue; - return QSize(panelWidth, static_cast(height() / ratio)); + multiSize += multiItem->width(); + } + } + + int panelWidth = qMin(iconSize * iconCount + multiSize + static_cast(spliterWidth / ratio), + static_cast((screenSize - DOCKSPACE) / deviceRatio)); + + return QSize(panelWidth, static_cast(dockSize / ratio)); } - iconSize = iconSize < width() ? iconSize : width(); - - int spliterHeight = m_fixedSpliter->isVisible() ? m_fixedSpliter->height() : 0; + int spliterHeight = m_fixedSpliter->isVisible() ? SPLITER_SIZE : 0; if (m_appSpliter->isVisible()) - spliterHeight += m_appSpliter->height(); + spliterHeight += SPLITER_SIZE; if (m_recentSpliter->isVisible()) - spliterHeight += m_recentSpliter->height(); + spliterHeight += SPLITER_SIZE; - int panelHeight = qMin(iconSize * iconCount + static_cast((spliterHeight + traySuitableSize.height() + 20) / ratio), - static_cast(screenSize / deviceRatio)); + int multiSize = 0; + // 计算每个多开窗口的尺寸 + if (multiWindowCount > 0) { + for (int i = 0; i < multiWindowCount; i++) { + AppMultiItem *multiItem = qobject_cast(m_multiWindowLayout->itemAt(i)->widget()); + if (!multiItem) + continue; - return QSize(width(), panelHeight); + multiSize += multiItem->height(); + } + } + + int panelHeight = qMin(iconSize * iconCount + multiSize + static_cast(spliterHeight / ratio), + static_cast((screenSize - DOCKSPACE)/ deviceRatio)); + + return QSize(dockSize, panelHeight); } void MainPanelControl::itemUpdated(DockItem *item) @@ -1204,12 +1166,10 @@ void MainPanelControl::paintEvent(QPaintEvent *event) int MainPanelControl::getScreenSize() const { QScreen *currentScreen = qApp->primaryScreen(); - if (m_dockScreen) { - DisplayManager *displayManager = DisplayManager::instance(); - QScreen *screen = displayManager->screen(m_dockScreen->current()); - if (screen) - currentScreen = screen; - } + DisplayManager *displayManager = DisplayManager::instance(); + QScreen *screen = displayManager->screen(DockScreen::instance()->current()); + if (screen) + currentScreen = screen; QRect screenRect = currentScreen->handle()->geometry(); if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) @@ -1225,15 +1185,11 @@ void MainPanelControl::resizeDockIcon() { int iconSize = 0; int tray_item_size = 0; - int iconCount = 0; // 总宽度 if (m_displayMode == DisplayMode::Fashion) { + int iconCount = 0; // 时尚模式 int totalLength = getScreenSize(); - QSize trayManagerSize = m_trayManagerWidget->suitableSize(); - // 减去右侧托盘和插件区域的宽度 - totalLength -= ((m_position == Position::Top) || (m_position == Position::Bottom)) ? trayManagerSize.width() : trayManagerSize.height(); - iconCount = m_fixedAreaLayout->count() + m_appAreaSonLayout->count(); if (m_recentAreaWidget->isVisible()) iconCount += m_recentLayout->count(); @@ -1251,7 +1207,7 @@ void MainPanelControl::resizeDockIcon() // 计算插件图标的最大或最小值 tray_item_size = qBound(20, iconSize, 40); if ((m_position == Position::Top) || (m_position == Position::Bottom)) { - tray_item_size = qMin(tray_item_size,height()); + tray_item_size = qMin(tray_item_size, height()); tray_item_size = std::min(tray_item_size, height() - 20); } else { tray_item_size = qMin(tray_item_size,width()); @@ -1356,12 +1312,13 @@ void MainPanelControl::resizeDockIcon() calcuDockIconSize(width(), iconSize, tray_item_size); } } + + Q_EMIT requestUpdate(); } void MainPanelControl::calcuDockIconSize(int w, int h, int traySize) { int appItemSize = qMin(w, h); - for (int i = 0; i < m_fixedAreaLayout->count(); ++i) m_fixedAreaLayout->itemAt(i)->widget()->setFixedSize(appItemSize, appItemSize); @@ -1552,20 +1509,8 @@ void MainPanelControl::resizeDesktopWidget() { if (m_position == Position::Right || m_position == Position::Left) { m_desktopWidget->setFixedSize(QWIDGETSIZE_MAX, DESKTOP_SIZE); - m_trayManagerWidget->setFixedWidth(QWIDGETSIZE_MAX); - m_trayManagerWidget->updateLayout(); - QSize suitableSize = m_trayManagerWidget->suitableSize(); - m_trayManagerWidget->setFixedHeight(suitableSize.height()); } else { m_desktopWidget->setFixedSize(DESKTOP_SIZE, QWIDGETSIZE_MAX); - // 在调整尺寸过程中,先设置高度,然后更新布局,因为更新布局的时候,里面的 - // Layout需要根据高度来调整布局的部件间距和边距,此时返回的尺寸会有所变化 - // 等布局更新后,再获取返回的尺寸来设置右侧的宽度 - // 如果是左右位置,原理一样 - m_trayManagerWidget->setFixedHeight(QWIDGETSIZE_MAX); - m_trayManagerWidget->updateLayout(); - QSize suitableSize = m_trayManagerWidget->suitableSize(); - m_trayManagerWidget->setFixedWidth(suitableSize.width()); } if (DisplayMode::Fashion == m_displayMode) diff --git a/frame/window/mainpanelcontrol.h b/frame/window/mainpanelcontrol.h index ef13a72c9..82e32e498 100755 --- a/frame/window/mainpanelcontrol.h +++ b/frame/window/mainpanelcontrol.h @@ -39,8 +39,6 @@ class DockItem; class PlaceholderItem; class AppDragWidget; class DesktopWidget; -class TrayManagerWindow; -class DockScreen; class RecentAppHelper; class ToolAppHelper; class MultiWindowHelper; @@ -50,16 +48,14 @@ class MainPanelControl : public QWidget Q_OBJECT public: - explicit MainPanelControl(QWidget *parent = nullptr); + explicit MainPanelControl(DockInter *dockInter, QWidget *parent = nullptr); void setPositonValue(Position position); void setDisplayMode(DisplayMode dislayMode); void resizeDockIcon(); void updatePluginsLayout(); - void setDockScreen(DockScreen *dockScreen); - QPainterPath areaPath(); - QSize suitableSize(int screenSize, double deviceRatio) const; + QSize suitableSize(const Position &position, int screenSize, double deviceRatio) const; public slots: void insertItem(const int index, DockItem *item); @@ -96,7 +92,6 @@ private: void resizeDesktopWidget(); bool checkNeedShowDesktop(); bool appIsOnDock(const QString &appDesktop); - void resetRadius(); void dockRecentApp(DockItem *dockItem); private Q_SLOTS: @@ -140,7 +135,6 @@ private: QWidget *m_toolSonAreaWidget; // 工具区域,用来存放回收站等工具 QBoxLayout *m_toolSonLayout; // 工具区域布局 - TrayManagerWindow *m_trayManagerWidget; QBoxLayout *m_pluginLayout; // 插件区域布局 DesktopWidget *m_desktopWidget; // 桌面预览区域 @@ -153,7 +147,6 @@ private: TrayPluginItem *m_tray; int m_dragIndex = -1; // 记录应用区域被拖拽图标的位置 - DockScreen *m_dockScreen; DockInter *m_dockInter; RecentAppHelper *m_recentHelper; ToolAppHelper *m_toolHelper; diff --git a/frame/window/mainwindow.cpp b/frame/window/mainwindow.cpp index 3f1a55a62..fb4d05462 100755 --- a/frame/window/mainwindow.cpp +++ b/frame/window/mainwindow.cpp @@ -25,6 +25,12 @@ #include "dockitemmanager.h" #include "menuworker.h" #include "proxyplugincontroller.h" +#include "windowmanager.h" +#include "dockscreen.h" +#include "dragwidget.h" +#include "multiscreenworker.h" +#include "constants.h" +#include "displaymanager.h" #include #include @@ -40,321 +46,47 @@ #include #include #include +#include +#include #include #include #include -#define SNI_WATCHER_SERVICE "org.kde.StatusNotifierWatcher" -#define SNI_WATCHER_PATH "/StatusNotifierWatcher" +#define DOCK_SCREEN DockScreen::instance() +#define DIS_INS DisplayManager::instance() -#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() +MainWindow::MainWindow(MultiScreenWorker *multiScreenWorker, QWidget *parent) + : MainWindowBase(multiScreenWorker, parent) + , m_mainPanel(new MainPanelControl(multiScreenWorker->dockInter(), this)) + , m_multiScreenWorker(multiScreenWorker) { - 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_wmHelper)) - , 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)) -{ - 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, 0)); - m_platformWindowHandle.setShadowColor(Qt::transparent); - 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 ] { this->setVisible(true); }); -} - -/** - * @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::reloadPlugins() -{ - if (qApp->property("PLUGINSLOADED").toBool()) { - return; - } - - // 发送事件,通知代理来加载插件 - PluginLoadEvent event; - QCoreApplication::sendEvent(qApp, &event); - - qApp->setProperty("PLUGINSLOADED", true); - // 退出安全模式 - qApp->setProperty("safeMode", false); -} - -/** - * @brief MainWindow::mousePressEvent - * @param e - * @note 右键显示任务栏的菜单 - */ -void MainWindow::mousePressEvent(QMouseEvent *e) -{ - e->ignore(); - if (e->button() == Qt::RightButton && this->geometry().contains(QCursor::pos())) { - QTimer::singleShot(10, this, [this]{ - QMenu *menu = new QMenu(this); - m_menuWorker->showDockSettingsMenu(menu); - }); - return; - } -} - -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(); + MainWindowBase::resizeEvent(event); - // 任务栏大小、位置、模式改变都会触发resize,发射大小改变信号,供依赖项目更新位置 - Q_EMIT panelGeometryChanged(); - - updateMaskArea(); m_mainPanel->updatePluginsLayout(); - m_shadowMaskOptimizeTimer->start(); - - return DBlurEffectWidget::resizeEvent(event); -} - -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()); -} - -void MainWindow::compositeChanged() -{ - const bool composite = m_wmHelper->hasComposite(); - setComposite(composite); - - m_shadowMaskOptimizeTimer->start(); + // 任务栏大小、位置、模式改变都会触发resize,发射大小改变信号,供依赖项目更新位置 + Q_EMIT requestUpdate(); } 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_mainPanel, &MainPanelControl::requestUpdate, 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, [ = ] { - m_multiScreenWorker->setStates(MultiScreenWorker::DockIsDraging, false); - qApp->setProperty(DRAG_STATE_PROP, false); - }); - - 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_mainPanel, &MainPanelControl::requestUpdate, this, &MainWindow::requestUpdate); } /** @@ -366,320 +98,77 @@ void MainWindow::resizeDockIcon() m_mainPanel->resizeDockIcon(); } -void MainWindow::updateMaskArea() -{ - QPainterPath path = m_mainPanel->areaPath(); - QPolygon polgon = path.toFillPolygon().toPolygon(); - setMask(polgon); -} - -/** - * @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 { - QVariant vRadius = qApp->property("EffectBorderRadius"); - if (vRadius.isNull()) - radius = dstyle.pixelMetric(DStyle::PM_TopLevelWindowRadius); - else - radius = vRadius.toInt(); - } - } - - m_platformWindowHandle.setWindowRadius(radius); - m_mainPanel->updatePluginsLayout(); - - updateMaskArea(); -} - -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) -{ - Q_UNUSED(enabled); - - setMaskColor(AutoColor); - - setMaskAlpha(m_multiScreenWorker->opacity()); - m_platformWindowHandle.setBorderWidth(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); - - 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_multiScreenWorker->setStates(MultiScreenWorker::DockIsDraging, true); - // 更新界面大小 - 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()) { + if (rect == this->geometry()) return; - } + DBlurEffectWidget::setGeometry(rect); - emit panelGeometryChanged(); + emit requestUpdate(); } -/** - * @brief 当进入安全模式时,通过此方法发送通知告知用户 - */ -void MainWindow::sendNotifications() +MainWindowBase::DockWindowType MainWindow::windowType() const { - 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(); - }); + return DockWindowType::MainWindow; +} + +void MainWindow::setPosition(const Position &position) +{ + MainWindowBase::setPosition(position); + m_mainPanel->setPositonValue(position); + + // 更新鼠标拖拽样式,在类内部设置到qApp单例上去 + if ((Top == position) || (Bottom == position)) + m_mainPanel->setCursor(Qt::SizeVerCursor); + else + m_mainPanel->setCursor(Qt::SizeHorCursor); +} + +void MainWindow::setDisplayMode(const Dock::DisplayMode &displayMode) +{ + m_mainPanel->setDisplayMode(displayMode); + MainWindowBase::setDisplayMode(displayMode); +} + +void MainWindow::updateParentGeometry(const Position &pos, const QRect &rect) +{ + setFixedSize(rect.size()); + setGeometry(rect); + + int panelSize = windowSize(); + QRect panelRect = rect; + switch (pos) { + case Position::Top: + m_mainPanel->move(0, rect.height() - panelSize); + panelRect.setHeight(panelSize); + break; + case Position::Left: + m_mainPanel->move(width() - panelSize, 0); + panelRect.setWidth(panelSize); + break; + case Position::Bottom: + m_mainPanel->move(0, 0); + panelRect.setHeight(panelSize); + break; + case Position::Right: + m_mainPanel->move(0, 0); + panelRect.setWidth(panelSize); + break; + } + m_mainPanel->setFixedSize(panelRect.size()); +} + +QSize MainWindow::suitableSize(const Position &pos, const int &screenSize, const double &deviceRatio) const +{ + return m_mainPanel->suitableSize(pos, screenSize, deviceRatio); +} + +void MainWindow::resetPanelGeometry() +{ + m_mainPanel->setFixedSize(size()); + m_mainPanel->move(0, 0); } diff --git a/frame/window/mainwindow.h b/frame/window/mainwindow.h index 40e4d9a88..2301a0931 100644 --- a/frame/window/mainwindow.h +++ b/frame/window/mainwindow.h @@ -24,17 +24,13 @@ #define MAINWINDOW_H #include "xcb_misc.h" -#include "statusnotifierwatcher_interface.h" -#include "mainpanelcontrol.h" #include "multiscreenworker.h" #include "touchsignalmanager.h" #include "imageutil.h" #include "utils.h" +#include "mainwindowbase.h" #include -#include -#include -#include #include @@ -43,189 +39,41 @@ DWIDGET_USE_NAMESPACE class MainPanelControl; class QTimer; class MenuWorker; -class DragWidget : public QWidget -{ - Q_OBJECT +class QScreen; -private: - bool m_dragStatus; - QPoint m_resizePoint; - -public: - explicit DragWidget(QWidget *parent = nullptr) - : QWidget(parent) - { - setObjectName("DragWidget"); - m_dragStatus = false; - } - -public slots: - void onTouchMove(double scaleX, double scaleY) - { - Q_UNUSED(scaleX); - Q_UNUSED(scaleY); - - static QPoint lastPos; - QPoint curPos = QCursor::pos(); - if (lastPos == curPos) { - return; - } - lastPos = curPos; - qApp->postEvent(this, new QMouseEvent(QEvent::MouseMove, mapFromGlobal(curPos) - , QPoint(), curPos, Qt::LeftButton, Qt::LeftButton - , Qt::NoModifier, Qt::MouseEventSynthesizedByApplication)); - } - -signals: - void dragPointOffset(QPoint); - void dragFinished(); - -private: - void mousePressEvent(QMouseEvent *event) override - { - // qt转发的触屏按下信号不进行响应 - if (event->source() == Qt::MouseEventSynthesizedByQt) { - return; - } - 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 - { - if (Utils::IS_WAYLAND_DISPLAY) - updateCursor(); - - QApplication::setOverrideCursor(cursor()); - } - - void leaveEvent(QEvent *) override - { - QApplication::setOverrideCursor(Qt::ArrowCursor); - } - - void updateCursor() - { - QString theme = Utils::SettingValue("com.deepin.xsettings", "/com/deepin/xsettings/", "gtk-cursor-theme-name", "bloom").toString(); - int cursorSize = Utils::SettingValue("com.deepin.xsettings", "/com/deepin/xsettings/", "gtk-cursor-theme-size", 24).toInt(); - Position position = static_cast(qApp->property("position").toInt()); - - static QString lastTheme; - static int lastPosition = -1; - static int lastCursorSize = -1; - if (theme != lastTheme || position != lastPosition || cursorSize != lastCursorSize) { - lastTheme = theme; - lastPosition = position; - lastCursorSize = cursorSize; - const char* cursorName = (position == Bottom || position == Top) ? "v_double_arrow" : "h_double_arrow"; - QCursor *newCursor = ImageUtil::loadQCursorFromX11Cursor(theme.toStdString().c_str(), cursorName, cursorSize); - if (!newCursor) - return; - - setCursor(*newCursor); - static QCursor *lastCursor = nullptr; - if (lastCursor) - delete lastCursor; - - lastCursor = newCursor; - } - } -}; - -class MainWindow : public DBlurEffectWidget +class MainWindow : public MainWindowBase { Q_OBJECT public: - explicit MainWindow(QWidget *parent = nullptr); - - void setEffectEnabled(const bool enabled); - void setComposite(const bool hasComposite); + explicit MainWindow(MultiScreenWorker *multiScreenWorker, QWidget *parent = nullptr); void setGeometry(const QRect &rect); - void sendNotifications(); friend class MainPanelControl; - MainPanelControl *panel() {return m_mainPanel;} - -public slots: - void launch(); - void callShow(); - void reloadPlugins(); + // 以下接口是实现基类的接口 + // 用来更新子区域的位置,一般用于在执行动画的过程中,根据当前的位置来更新里面panel的大小 + DockWindowType windowType() const override; + void setPosition(const Dock::Position &position) override; + void setDisplayMode(const Dock::DisplayMode &displayMode) override; + void updateParentGeometry(const Dock::Position &pos, const QRect &rect) override; + QSize suitableSize(const Dock::Position &pos, const int &screenSize, const double &deviceRatio) const override; + void resetPanelGeometry() override; private: using QWidget::show; - void mousePressEvent(QMouseEvent *e) override; - void keyPressEvent(QKeyEvent *e) override; - void enterEvent(QEvent *e) override; - void mouseMoveEvent(QMouseEvent *e) override; - void moveEvent(QMoveEvent *event) override; void resizeEvent(QResizeEvent *event) override; - - void initMember(); - void initSNIHost(); - void initComponents(); void initConnections(); - void resizeDockIcon(); - void updateMaskArea(); - -signals: - void panelGeometryChanged(); - -public slots: - void RegisterDdeSession(); - void resizeDock(int offset, bool dragging); - void resetDragWindow(); // 任务栏调整高度或宽度后需调用此函数 - -private slots: - void compositeChanged(); - void adjustShadowMask(); - - void onDbusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); - void onMainWindowSizeChanged(QPoint offset); - void themeTypeChanged(DGuiApplicationHelper::ColorType themeType); - void touchRequestResizeDock(); private: MainPanelControl *m_mainPanel; // 任务栏 - DPlatformWindowHandle m_platformWindowHandle; - DWindowManagerHelper *m_wmHelper; MultiScreenWorker *m_multiScreenWorker; // 多屏幕管理 - MenuWorker *m_menuWorker; - QTimer *m_shadowMaskOptimizeTimer; - QDBusConnectionInterface *m_dbusDaemonInterface; - org::kde::StatusNotifierWatcher *m_sniWatcher; // DBUS状态通知 - DragWidget *m_dragWidget; QString m_sniHostService; - bool m_launched; QString m_registerKey; QStringList m_registerKeys; - - QTimer *m_updateDragAreaTimer; }; #endif // MAINWINDOW_H diff --git a/frame/window/mainwindowbase.cpp b/frame/window/mainwindowbase.cpp new file mode 100644 index 000000000..1ec2c9faf --- /dev/null +++ b/frame/window/mainwindowbase.cpp @@ -0,0 +1,606 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 "mainwindowbase.h" +#include "dragwidget.h" +#include "multiscreenworker.h" +#include "dockscreen.h" +#include "touchsignalmanager.h" +#include "displaymanager.h" +#include "menuworker.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DRAG_AREA_SIZE (5) + +// 任务栏圆角最小的时候,任务栏的高度值 +#define MIN_RADIUS_WINDOWSIZE 46 +// 任务栏圆角最小值和最大值的差值 +#define MAX_MIN_RADIUS_DIFFVALUE 6 +// 最小圆角值 +#define MIN_RADIUS 12 + +#define DOCK_SCREEN DockScreen::instance() +#define DIS_INS DisplayManager::instance() + +DGUI_USE_NAMESPACE + +MainWindowBase::MainWindowBase(MultiScreenWorker *multiScreenWorker, QWidget *parent) + : DBlurEffectWidget(parent) + , m_displayMode(Dock::DisplayMode::Efficient) + , m_position(Dock::Position::Bottom) + , m_dockInter(multiScreenWorker->dockInter()) + , m_dragWidget(new DragWidget(this)) + , m_multiScreenWorker(multiScreenWorker) + , m_updateDragAreaTimer(new QTimer(this)) + , m_platformWindowHandle(this) + , m_shadowMaskOptimizeTimer(new QTimer(this)) + , m_isShow(false) + , m_borderRadius(0) + , m_order(0) +{ + initUi(); + initAttribute(); + initConnection(); + initMember(); +} + +MainWindowBase::~MainWindowBase() +{ +} + +void MainWindowBase::setOrder(int order) +{ + m_order = order; +} + +int MainWindowBase::order() const +{ + return m_order; +} + +void MainWindowBase::initAttribute() +{ + 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时无效 + setAttribute(Qt::WA_NativeWindow); + windowHandle()->setProperty("_d_dwayland_window-type", "dock"); + } + + 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); + + m_dragWidget->setMouseTracking(true); + m_dragWidget->setFocusPolicy(Qt::NoFocus); + + if ((Dock::Top == m_position) || (Dock::Bottom == m_position)) + m_dragWidget->setCursor(Qt::SizeVerCursor); + else + m_dragWidget->setCursor(Qt::SizeHorCursor); +} + +void MainWindowBase::initConnection() +{ + connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasCompositeChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); + connect(m_shadowMaskOptimizeTimer, &QTimer::timeout, this, &MainWindowBase::adjustShadowMask, Qt::QueuedConnection); + + connect(&m_platformWindowHandle, &DPlatformWindowHandle::frameMarginsChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); + connect(&m_platformWindowHandle, &DPlatformWindowHandle::windowRadiusChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); + + connect(m_dragWidget, &DragWidget::dragFinished, this, [ = ] { + m_multiScreenWorker->setStates(MultiScreenWorker::DockIsDraging, false); + }); + + // -拖拽任务栏改变高度或宽度------------------------------------------------------------------------------- + connect(m_updateDragAreaTimer, &QTimer::timeout, this, &MainWindowBase::resetDragWindow); + //TODO 后端考虑删除这块,目前还不能删除,调整任务栏高度的时候,任务栏外部区域有变化 + connect(m_updateDragAreaTimer, &QTimer::timeout, m_multiScreenWorker, &MultiScreenWorker::onRequestUpdateRegionMonitor); + + connect(m_dragWidget, &DragWidget::dragPointOffset, this, &MainWindowBase::onMainWindowSizeChanged); + connect(m_dragWidget, &DragWidget::dragFinished, this, &MainWindowBase::resetDragWindow); // 更新拖拽区域 + connect(TouchSignalManager::instance(), &TouchSignalManager::touchMove, m_dragWidget, &DragWidget::onTouchMove); + connect(TouchSignalManager::instance(), &TouchSignalManager::middleTouchPress, this, &MainWindowBase::touchRequestResizeDock); + + connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &MainWindowBase::onThemeTypeChanged); + connect(m_multiScreenWorker, &MultiScreenWorker::opacityChanged, this, &MainWindowBase::setMaskAlpha, Qt::QueuedConnection); + + onThemeTypeChanged(DGuiApplicationHelper::instance()->themeType()); + QMetaObject::invokeMethod(this, &MainWindowBase::onCompositeChanged); +} + +void MainWindowBase::initMember() +{ + //INFO 这里要大于动画的300ms,否则可能动画过程中这个定时器就被触发了 + m_updateDragAreaTimer->setInterval(500); + m_updateDragAreaTimer->setSingleShot(true); + m_shadowMaskOptimizeTimer->setSingleShot(true); + m_shadowMaskOptimizeTimer->setInterval(100); +} + +int MainWindowBase::getBorderRadius() const +{ + if (!DWindowManagerHelper::instance()->hasComposite() || m_multiScreenWorker->displayMode() != DisplayMode::Fashion) + return 0; + + if (Dtk::Core::DSysInfo::isCommunityEdition()) { // 社区版圆角与专业版不同 + DPlatformTheme *theme = DGuiApplicationHelper::instance()->systemTheme(); + return theme->windowRadius(0); + } + + int size = ((m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) ? height() : width()); + return qMin(MAX_MIN_RADIUS_DIFFVALUE, qMax(size - MIN_RADIUS_WINDOWSIZE, 0)) + MIN_RADIUS; +} + +/** + * @brief MainWindow::onMainWindowSizeChanged 任务栏拖拽过程中会不停调用此方法更新自身大小 + * @param offset 拖拽时的坐标偏移量 + */ +void MainWindowBase::onMainWindowSizeChanged(QPoint offset) +{ + QScreen *screen = DIS_INS->screen(DOCK_SCREEN->current()); + if (!screen) + return; + + const QRect rect = getDockGeometry(screen, position(), displayMode(), Dock::HideState::Show); + QRect newRect; + switch (m_multiScreenWorker->position()) { + case Top: { + newRect.setX(rect.x()); + newRect.setY(rect.y()); + newRect.setWidth(rect.width()); + newRect.setHeight(qBound(DOCK_MIN_SIZE, rect.height() + offset.y(), DOCK_MAX_SIZE)); + } + break; + case Bottom: { + newRect.setX(rect.x()); + newRect.setY(rect.y() + rect.height() - qBound(DOCK_MIN_SIZE, rect.height() - offset.y(), DOCK_MAX_SIZE)); + newRect.setWidth(rect.width()); + newRect.setHeight(qBound(DOCK_MIN_SIZE, rect.height() - offset.y(), DOCK_MAX_SIZE)); + } + break; + case Left: { + newRect.setX(rect.x()); + newRect.setY(rect.y()); + newRect.setWidth(qBound(DOCK_MIN_SIZE, rect.width() + offset.x(), DOCK_MAX_SIZE)); + newRect.setHeight(rect.height()); + } + break; + case Right: { + newRect.setX(rect.x() + rect.width() - qBound(DOCK_MIN_SIZE, rect.width() - offset.x(), DOCK_MAX_SIZE)); + newRect.setY(rect.y()); + newRect.setWidth(qBound(DOCK_MIN_SIZE, rect.width() - offset.x(), DOCK_MAX_SIZE)); + newRect.setHeight(rect.height()); + } + break; + } + + m_multiScreenWorker->setStates(MultiScreenWorker::DockIsDraging, true); + + setFixedSize(newRect.size()); + move(newRect.topLeft()); + resetPanelGeometry(); + + Q_EMIT requestUpdate(); +} + +void MainWindowBase::updateDragGeometry() +{ + switch (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(), 20); + 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; + } + + m_dragWidget->raise(); + if ((Top == position()) || (Bottom == position())) { + m_dragWidget->setCursor(Qt::SizeVerCursor); + } else { + m_dragWidget->setCursor(Qt::SizeHorCursor); + } +} + +void MainWindowBase::resetDragWindow() +{ + updateDragGeometry(); + QScreen *screen = DIS_INS->screen(DOCK_SCREEN->current()); + if (!screen) + return; + + QRect currentRect = getDockGeometry(screen, position(), displayMode(), Dock::HideState::Show); + + // 这个时候屏幕有可能是隐藏的,不能直接使用this->width()这种去设置任务栏的高度,而应该保证原值 + int dockSize = 0; + if (m_multiScreenWorker->position() == Position::Left + || m_multiScreenWorker->position() == Position::Right) { + dockSize = this->width() == 0 ? currentRect.width() : this->width(); + } else { + dockSize = this->height() == 0 ? currentRect.height() : this->height(); + } + + /** FIX ME + * 作用:限制dockSize的值在40~100之间。 + * 问题1:如果dockSize为39,会导致dock的mainwindow高度变成99,显示的内容高度却是39。 + * 问题2:dockSize的值在这里不应该为39,但在高分屏上开启缩放后,拉高任务栏操作会概率出现。 + * 暂时未分析出原因,后面再修改。 + */ + dockSize = qBound(DOCK_MIN_SIZE, dockSize, DOCK_MAX_SIZE); + + // 通知窗管和后端更新数据 + m_multiScreenWorker->updateDaemonDockSize(dockSize); // 1.先更新任务栏高度 + m_multiScreenWorker->requestUpdateFrontendGeometry(); // 2.再更新任务栏位置,保证先1再2 + m_multiScreenWorker->requestNotifyWindowManager(); + m_multiScreenWorker->requestUpdateRegionMonitor(); // 界面发生变化,应更新监控区域 +} + +void MainWindowBase::touchRequestResizeDock() +{ + const QPoint touchPos(QCursor::pos()); + QRect dockRect = geometry(); + // 隐藏状态返回 + if (width() == 0 || height() == 0) + return; + + int resizeHeight = Utils::SettingValue("com.deepin.dde.dock.touch", QByteArray(), "resizeHeight", 7).toInt(); + + QRect touchRect; + // 任务栏屏幕 内侧边线 内外resizeHeight距离矩形区域内长按可拖动任务栏高度 + switch (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)); +} + +void MainWindowBase::adjustShadowMask() +{ + if (!m_isShow || m_shadowMaskOptimizeTimer->isActive()) + return; + + m_platformWindowHandle.setWindowRadius(m_borderRadius); +} + +void MainWindowBase::onCompositeChanged() +{ + setMaskColor(AutoColor); + + setMaskAlpha(m_multiScreenWorker->opacity()); + m_platformWindowHandle.setBorderWidth(0); + + m_shadowMaskOptimizeTimer->start(); +} + +void MainWindowBase::onThemeTypeChanged(DGuiApplicationHelper::ColorType themeType) +{ + if (DWindowManagerHelper::instance()->hasComposite()) { + if (themeType == DGuiApplicationHelper::DarkType) { + QColor color = Qt::black; + color.setAlpha(255 * 0.3); + m_platformWindowHandle.setBorderColor(color); + } else { + m_platformWindowHandle.setBorderColor(QColor(QColor::Invalid)); + } + } +} + +void MainWindowBase::setDisplayMode(const Dock::DisplayMode &displayMode) +{ + m_displayMode = displayMode; + adjustShadowMask(); +} + +void MainWindowBase::setPosition(const Dock::Position &position) +{ + m_position = position; +} + +QRect MainWindowBase::getDockGeometry(QScreen *screen, const Dock::Position &pos, const Dock::DisplayMode &displaymode, const Dock::HideState &hideState, bool withoutScale) const +{ + QList topMainWindows; // 所有的顶层主窗口列表 + QList lessOrderMainWindows; // 所有在当前窗口之前的主窗口 + QWidgetList topWidgets = qApp->topLevelWidgets(); + for (QWidget *widget : topWidgets) { + MainWindowBase *currentWindow = qobject_cast(widget); + if (!currentWindow || !currentWindow->isVisible()) + continue; + + topMainWindows << currentWindow; + if (currentWindow->order() < order()) + lessOrderMainWindows << currentWindow; + } + + if (!topMainWindows.contains(this)) + return QRect(); + + // 对当前窗口前面的所有窗口按照order进行排序 + sort(lessOrderMainWindows.begin(), lessOrderMainWindows.end(), [](MainWindowBase const *window1, MainWindowBase const *window2) { + return window1->order() < window2->order(); + }); + QRect rect; + const double ratio = withoutScale ? 1 : qApp->devicePixelRatio(); + const int margin = static_cast((displaymode == DisplayMode::Fashion ? 10 : 0) * (withoutScale ? qApp->devicePixelRatio() : 1)); + int dockSize = 0; + if (hideState == Dock::HideState::Show) + dockSize = windowSize(); + + // 拿到当前显示器缩放之前的分辨率 + QRect screenRect = screen->handle()->geometry(); + // 计算所有的窗口的总尺寸 + int totalSize = 0; + switch (pos) { + case Dock::Position::Top: + case Dock::Position::Bottom: { + // 计算任务栏的总的尺寸 + int width = 0; + for (MainWindowBase const *mainWindow : topMainWindows) { + QSize windowSize = mainWindow->suitableSize(pos, screenRect.width(), ratio); + totalSize += windowSize.width() + mainWindow->dockSpace(); + if (mainWindow == this) + width = windowSize.width(); + } + + // 计算第一个窗口的X坐标 + int x = screenRect.x() + (static_cast((screenRect.width() / ratio) - totalSize) / 2); + // 计算当前的X坐标 + for (MainWindowBase const *mainWindow : lessOrderMainWindows) { + x += mainWindow->suitableSize(pos, screenRect.width(), ratio).width() + mainWindow->dockSpace(); + } + int y = 0; + if (pos == Dock::Position::Top) + y = (screenRect.y() + static_cast(margin / ratio)); + else + y = (screenRect.y() + static_cast(screenRect.height() / ratio - margin / ratio)) - dockSize; + rect.setX(x); + rect.setY(y); + rect.setWidth(width); + rect.setHeight(dockSize); + break; + } + case Dock::Position::Left: + case Dock::Position::Right: { + int height = 0; + for (MainWindowBase const *mainWindow : topMainWindows) { + QSize windowSize = mainWindow->suitableSize(pos, screenRect.height(), ratio); + totalSize += windowSize.height() + mainWindow->dockSpace(); + if (mainWindow == this) + height = windowSize.height(); + } + int x = 0; + if (pos == Dock::Position::Left) + x = screenRect.x() + static_cast(margin / ratio); + else + x = screenRect.x() + static_cast(screenRect.width() /ratio - margin / ratio) - dockSize; + + int y = screenRect.y() + static_cast(((screenRect.height() / ratio) - totalSize) / 2); + // 计算y坐标 + for (MainWindowBase const *mainWindow : lessOrderMainWindows) + y += mainWindow->suitableSize(pos, screenRect.height(), ratio).height() + mainWindow->dockSpace(); + + rect.setX(x); + rect.setY(y); + rect.setWidth(dockSize); + rect.setHeight(height); + break; + } + } + return rect; +} + +QVariantAnimation *MainWindowBase::createAnimation(QScreen *screen, const Dock::Position &pos, const Dock::AniAction &act) +{ + /** FIXME + * 在高分屏2.75倍缩放的情况下,mainWindowGeometry返回的任务栏高度有问题(实际是40,返回是39) + * 在这里增加判断,当返回值在范围(38,42)开区间内,均认为任务栏显示位置正确,直接返回,不执行动画 + * 也就是在实际值基础上下浮动1像素的误差范围 + * 正常屏幕情况下是没有这个问题的 + */ + QRect mainwindowRect = geometry(); + const QRect dockShowRect = getDockGeometry(screen, pos, m_multiScreenWorker->displayMode(), Dock::HideState::Show); + const QRect &dockHideRect = getDockGeometry(screen, pos, m_multiScreenWorker->displayMode(), Dock::HideState::Hide); + if (act == Dock::AniAction::Show) { + if (pos == Position::Top || pos == Position::Bottom) { + if (qAbs(dockShowRect.height() - mainwindowRect.height()) <= 1 + && mainwindowRect.contains(dockShowRect.center())) + return nullptr; + } else if (pos == Position::Left || pos == Position::Right) { + if (qAbs(dockShowRect.width() - mainwindowRect.width()) <= 1 + && mainwindowRect.contains(dockShowRect.center())) + return nullptr; + } + } + if (act == Dock::AniAction::Hide && dockHideRect.size() == mainwindowRect.size()) + return nullptr; + + // 开始播放动画 + QVariantAnimation *ani = new QVariantAnimation(nullptr); + ani->setEasingCurve(QEasingCurve::InOutCubic); +#ifndef DISABLE_SHOW_ANIMATION + const bool composite = DWindowManagerHelper::instance()->hasComposite(); // 判断是否开启特效模式 + const int duration = composite ? ANIMATIONTIME : 0; +#else + const int duration = 0; +#endif + ani->setDuration(duration); + + connect(ani, &QVariantAnimation::valueChanged, this, [ = ](const QVariant &value) { + if ((!m_multiScreenWorker->testState(MultiScreenWorker::ShowAnimationStart) + && !m_multiScreenWorker->testState(MultiScreenWorker::HideAnimationStart) + && !m_multiScreenWorker->testState(MultiScreenWorker::ChangePositionAnimationStart)) + || ani->state() != QVariantAnimation::State::Running) + return; + + updateParentGeometry(pos, value.value()); + }); + + switch (act) { + case Dock::AniAction::Show: { + ani->setStartValue(dockHideRect); + ani->setEndValue(dockShowRect); + connect(ani, &QVariantAnimation::finished, this, [ = ]{ + updateParentGeometry(pos, dockShowRect); + }); + break; + } + case Dock::AniAction::Hide: { + ani->setStartValue(dockShowRect); + ani->setEndValue(dockHideRect); + connect(ani, &QVariantAnimation::finished, this, [ = ]{ + updateParentGeometry(pos, dockHideRect); + }); + break; + } + } + + return ani; +} + +Dock::DisplayMode MainWindowBase::displayMode() const +{ + return m_displayMode; +} + +Dock::Position MainWindowBase::position() const +{ + return m_position; +} + +int MainWindowBase::windowSize() const +{ + if (m_displayMode == Dock::DisplayMode::Efficient) + return m_dockInter->windowSizeEfficient(); + + return m_dockInter->windowSizeFashion(); +} + +bool MainWindowBase::isDraging() const +{ + return m_dragWidget->isDraging(); +} + +int MainWindowBase::dockSpace() const +{ + return DOCKSPACE; +} + +void MainWindowBase::initUi() +{ + DPlatformWindowHandle::enableDXcbForWindow(this, true); + m_platformWindowHandle.setEnableBlurWindow(true); + m_platformWindowHandle.setTranslucentBackground(true); + m_platformWindowHandle.setShadowOffset(QPoint(0, 0)); + m_platformWindowHandle.setShadowColor(Qt::transparent); +} + +void MainWindowBase::resizeEvent(QResizeEvent *event) +{ + updateDragGeometry(); + + int borderRadius = getBorderRadius(); + if (borderRadius != m_borderRadius) { + m_borderRadius = borderRadius; + updateRadius(m_borderRadius); + } + + m_shadowMaskOptimizeTimer->start(); +} + +void MainWindowBase::moveEvent(QMoveEvent *) +{ + updateDragGeometry(); +} + +void MainWindowBase::enterEvent(QEvent *e) +{ + QWidget::enterEvent(e); + + if (QApplication::overrideCursor() && QApplication::overrideCursor()->shape() != Qt::ArrowCursor) + QApplication::restoreOverrideCursor(); +} + +void MainWindowBase::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::RightButton && geometry().contains(QCursor::pos())) { + m_multiScreenWorker->onAutoHideChanged(false); + MenuWorker menuWorker; + menuWorker.exec(); + m_multiScreenWorker->onAutoHideChanged(true); + } + + DBlurEffectWidget::mousePressEvent(event); +} + +void MainWindowBase::showEvent(QShowEvent *event) +{ + if (!m_isShow) { + m_isShow = true; + m_shadowMaskOptimizeTimer->start(); + } + + DBlurEffectWidget::showEvent(event); +} diff --git a/frame/window/mainwindowbase.h b/frame/window/mainwindowbase.h new file mode 100644 index 000000000..ff528f49d --- /dev/null +++ b/frame/window/mainwindowbase.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 MAINWINDOWBASE_H +#define MAINWINDOWBASE_H + +#include "constants.h" +#include "dbusutil.h" + +#include +#include +#include + +#include +#include +#include + +class DragWidget; +class MultiScreenWorker; + +DWIDGET_USE_NAMESPACE + +class MainWindowBase : public DBlurEffectWidget +{ + Q_OBJECT + +public: + enum class DockWindowType { + MainWindow, // 主窗口 + TrayWindow // 主窗口之外的其他窗口 + }; + +public: + explicit MainWindowBase(MultiScreenWorker *multiScreenWorker, QWidget *parent = Q_NULLPTR); + virtual ~MainWindowBase(); + + void setOrder(int order); // 窗体展示的顺序,按照左到右和上到下 + int order() const; + + virtual DockWindowType windowType() const = 0; + virtual void setDisplayMode(const Dock::DisplayMode &displayMode); + virtual void setPosition(const Dock::Position &position); + // 用来更新子区域的位置,一般用于在执行动画的过程中,根据当前的位置来更新里面panel的大小 + virtual void updateParentGeometry(const Dock::Position &pos, const QRect &rect) = 0; + virtual QRect getDockGeometry(QScreen *screen, const Dock::Position &pos, const Dock::DisplayMode &displaymode, const Dock::HideState &hideState, bool withoutScale = false) const; + QVariantAnimation *createAnimation(QScreen *screen, const Dock::Position &pos, const Dock::AniAction &act); + virtual void resetPanelGeometry() {} // 重置内部区域,为了让内部区域和当前区域始终保持一致 + virtual int dockSpace() const; // 与后面窗体之间的间隔 + +Q_SIGNALS: + void requestUpdate(); + +protected: + void resizeEvent(QResizeEvent *event) override; + void moveEvent(QMoveEvent *) override; + void enterEvent(QEvent *e) override; + void mousePressEvent(QMouseEvent *event) override; + void showEvent(QShowEvent *event) override; + + Dock::DisplayMode displayMode() const; + Dock::Position position() const; + + int windowSize() const; + + bool isDraging() const; + + virtual void updateRadius(int borderRadius) {} + virtual QSize suitableSize(const Dock::Position &pos, const int &screenSize, const double &deviceRatio) const = 0; + +private: + void initUi(); + void initAttribute(); + void initConnection(); + void initMember(); + void updateDragGeometry(); + + int getBorderRadius() const; + +private Q_SLOTS: + void onMainWindowSizeChanged(QPoint offset); + void resetDragWindow(); + void touchRequestResizeDock(); + void adjustShadowMask(); + void onCompositeChanged(); + void onThemeTypeChanged(DGuiApplicationHelper::ColorType themeType); + +private: + Dock::DisplayMode m_displayMode; + Dock::Position m_position; + DockInter *m_dockInter; + DragWidget *m_dragWidget; + MultiScreenWorker *m_multiScreenWorker; + QTimer *m_updateDragAreaTimer; + DPlatformWindowHandle m_platformWindowHandle; + QTimer *m_shadowMaskOptimizeTimer; + bool m_isShow; + int m_borderRadius; + int m_order; +}; + +#endif // MAINWINDOWBASE_H diff --git a/frame/window/quickpluginwindow.cpp b/frame/window/quickpluginwindow.cpp index bf11670fa..573510990 100644 --- a/frame/window/quickpluginwindow.cpp +++ b/frame/window/quickpluginwindow.cpp @@ -131,6 +131,11 @@ void QuickPluginWindow::dragPlugin(PluginsItemInterface *item) Q_EMIT itemCountChanged(); } +QSize QuickPluginWindow::suitableSize() const +{ + return suitableSize(m_position); +} + void QuickPluginWindow::addPlugin(QuickSettingItem *item) { for (int i = 0; i < m_mainLayout->count(); i++) { @@ -163,9 +168,9 @@ void QuickPluginWindow::addPlugin(QuickSettingItem *item) Q_EMIT itemCountChanged(); } -QSize QuickPluginWindow::suitableSize() +QSize QuickPluginWindow::suitableSize(const Dock::Position &position) const { - if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + if (position == Dock::Position::Top || position == Dock::Position::Bottom) return QSize((ITEMSPACE + ICONWIDTH) * m_mainLayout->count() + ITEMSPACE, ITEMSIZE); int height = 0; diff --git a/frame/window/quickpluginwindow.h b/frame/window/quickpluginwindow.h index db7bbf70a..ffad4a3a4 100644 --- a/frame/window/quickpluginwindow.h +++ b/frame/window/quickpluginwindow.h @@ -52,7 +52,8 @@ public: void setPositon(Dock::Position position); void dragPlugin(PluginsItemInterface *item); - QSize suitableSize(); + QSize suitableSize() const; + QSize suitableSize(const Dock::Position &position) const; Q_SIGNALS: void itemCountChanged(); diff --git a/frame/window/systempluginwindow.cpp b/frame/window/systempluginwindow.cpp index 478b4ccaf..d725d0ea7 100644 --- a/frame/window/systempluginwindow.cpp +++ b/frame/window/systempluginwindow.cpp @@ -72,17 +72,22 @@ void SystemPluginWindow::setPositon(Position position) } } -QSize SystemPluginWindow::suitableSize() +QSize SystemPluginWindow::suitableSize() const +{ + return suitableSize(m_position); +} + +QSize SystemPluginWindow::suitableSize(const Position &position) const { QObjectList childs = children(); - if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { int itemWidth = 0; for (QObject *childObject : childs) { StretchPluginsItem *childItem = qobject_cast(childObject); if (!childItem) continue; - itemWidth += childItem->suitableSize().width(); + itemWidth += childItem->suitableSize(position).width(); } return QSize(itemWidth, QWIDGETSIZE_MAX); @@ -94,7 +99,7 @@ QSize SystemPluginWindow::suitableSize() if (!item) continue; - itemHeight += item->suitableSize().height(); + itemHeight += item->suitableSize(position).height(); } return QSize(QWIDGETSIZE_MAX, itemHeight); @@ -175,6 +180,11 @@ QString StretchPluginsItem::itemKey() const return m_itemKey; } +QSize StretchPluginsItem::suitableSize() const +{ + return suitableSize(m_position); +} + PluginsItemInterface *StretchPluginsItem::pluginInter() const { return m_pluginInter; @@ -210,31 +220,38 @@ void StretchPluginsItem::paintEvent(QPaintEvent *event) painter.drawPixmap(rctPixmap, icon.pixmap(iconSize, iconSize)); } -QSize StretchPluginsItem::suitableSize() const +QSize StretchPluginsItem::suitableSize(const Position &position) const { int iconSize = static_cast(ICONSIZE * (qApp->devicePixelRatio())); - if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { - int textWidth = QFontMetrics(textFont()).boundingRect(m_pluginInter->pluginDisplayName()).width(); + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { + int textWidth = QFontMetrics(textFont(position)).boundingRect(m_pluginInter->pluginDisplayName()).width(); return QSize(qMax(textWidth, iconSize) + 10 * 2, -1); } - int height = 6; // 图标上边距6 - height += iconSize; // 图标尺寸20 - height += ICONTEXTSPACE; // 图标与文字间距6 - height += QFontMetrics(textFont()).height(); // 文本高度 - height += 4; // 下间距4 + int height = 6; // 图标上边距6 + height += iconSize; // 图标尺寸20 + height += ICONTEXTSPACE; // 图标与文字间距6 + height += QFontMetrics(textFont(position)).height(); // 文本高度 + height += 4; // 下间距4 return QSize(-1, height); } QFont StretchPluginsItem::textFont() const { - if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + return textFont(m_position); +} + +QFont StretchPluginsItem::textFont(const Position &position) const +{ + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { static QList fonts{ DFontSizeManager::instance()->t9(), DFontSizeManager::instance()->t8(), DFontSizeManager::instance()->t7(), DFontSizeManager::instance()->t6() }; #define MINHEIGHT 50 - int index = qMin(qMax((height() - MINHEIGHT) / 2, 0), fonts.size() - 1); + // 如果当前的实际位置和请求的位置不一致,说明当前正在切换位置,此时将它的宽度作为它的高度(左到下切换的时候,左侧的宽度和下面的高度一致) + int size = (m_position == position ? height() : width()); + int index = qMin(qMax((size - MINHEIGHT) / 2, 0), fonts.size() - 1); return fonts[index]; } diff --git a/frame/window/systempluginwindow.h b/frame/window/systempluginwindow.h index a21ba18a4..0e92f0864 100644 --- a/frame/window/systempluginwindow.h +++ b/frame/window/systempluginwindow.h @@ -43,7 +43,8 @@ public: explicit SystemPluginWindow(QWidget *parent = nullptr); ~SystemPluginWindow() override; void setPositon(Dock::Position position); - QSize suitableSize(); + QSize suitableSize() const; + QSize suitableSize(const Dock::Position &position) const; Q_SIGNALS: void itemChanged(); @@ -75,6 +76,7 @@ public: PluginsItemInterface *pluginInter() const; QString itemKey() const; QSize suitableSize() const; + QSize suitableSize(const Dock::Position &position) const; inline ItemType itemType() const override { return DockItem::StretchPlugin; } @@ -89,6 +91,7 @@ protected: private: void mouseClick(); QFont textFont() const; + QFont textFont(const Dock::Position &position) const; bool needShowText() const; private: diff --git a/frame/window/tray/tray_gridview.cpp b/frame/window/tray/tray_gridview.cpp index 3f51f99cf..957b29b97 100644 --- a/frame/window/tray/tray_gridview.cpp +++ b/frame/window/tray/tray_gridview.cpp @@ -59,6 +59,11 @@ Dock::Position TrayGridView::position() const } QSize TrayGridView::suitableSize() const +{ + return suitableSize(m_positon); +} + +QSize TrayGridView::suitableSize(const Dock::Position &position) const { TrayModel *dataModel = qobject_cast(model()); if (!dataModel) @@ -88,21 +93,38 @@ QSize TrayGridView::suitableSize() const } return QSize(width, height); } - if (m_positon == Dock::Position::Top || m_positon == Dock::Position::Bottom) { + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { int length = spacing() + 2; - for (int i = 0; i < dataModel->rowCount(); i++) { - QModelIndex index = dataModel->index(i, 0); - QRect indexRect = visualRect(index); - length += indexRect.width() + spacing(); + if (m_positon == Dock::Position::Top || m_positon == Dock::Position::Bottom) { + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + QRect indexRect = visualRect(index); + length += indexRect.width() + spacing(); + } + } else { + // 如果是从左右切换过来的,此时还未进入上下位置,则将当前位置的高度作为计算左右位置的宽度 + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + QRect indexRect = visualRect(index); + length += indexRect.height() + spacing(); + } } return QSize(length, -1); } int height = spacing() + 2; - for (int i = 0; i < dataModel->rowCount(); i++) { - QModelIndex index = dataModel->index(i, 0); - QRect indexRect = visualRect(index); - height += indexRect.height() + spacing(); + if (m_positon == Dock::Position::Left || m_positon == Dock::Position::Right) { + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + QRect indexRect = visualRect(index); + height += indexRect.height() + spacing(); + } + } else { + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + QRect indexRect = visualRect(index); + height += indexRect.width() + spacing(); + } } return QSize(-1, height); diff --git a/frame/window/tray/tray_gridview.h b/frame/window/tray/tray_gridview.h index e06cb0f30..9a498453d 100644 --- a/frame/window/tray/tray_gridview.h +++ b/frame/window/tray/tray_gridview.h @@ -39,6 +39,7 @@ public: void setPosition(Dock::Position position); Dock::Position position() const; QSize suitableSize() const; + QSize suitableSize(const Dock::Position &position) const; void setDragDistance(int pixel); void setAnimationProperty(const QEasingCurve::Type easing, const int duringTime = 250); void moveAnimation(); diff --git a/frame/window/traymainwindow.cpp b/frame/window/traymainwindow.cpp new file mode 100644 index 000000000..6f8f9d58e --- /dev/null +++ b/frame/window/traymainwindow.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 "traymainwindow.h" +#include "traymanagerwindow.h" +#include "dragwidget.h" +#include "dockscreen.h" +#include "displaymanager.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define DOCK_SCREEN DockScreen::instance() +#define DIS_INS DisplayManager::instance() + +TrayMainWindow::TrayMainWindow(MultiScreenWorker *multiScreenWorker, QWidget *parent) + : MainWindowBase(multiScreenWorker, parent) + , m_trayManager(new TrayManagerWindow(this)) + , m_multiScreenWorker(multiScreenWorker) +{ + initUI(); + initConnection(); +} + +void TrayMainWindow::setPosition(const Dock::Position &position) +{ + MainWindowBase::setPosition(position); + m_trayManager->setPositon(position); +} + +TrayManagerWindow *TrayMainWindow::trayManagerWindow() const +{ + return m_trayManager; +} + +void TrayMainWindow::setDisplayMode(const Dock::DisplayMode &displayMode) +{ + // 只有在时尚模式下才显示 + setVisible(displayMode == Dock::DisplayMode::Fashion); + MainWindowBase::setDisplayMode(displayMode); +} + +MainWindowBase::DockWindowType TrayMainWindow::windowType() const +{ + return DockWindowType::TrayWindow; +} + +void TrayMainWindow::updateParentGeometry(const Dock::Position &position, const QRect &rect) +{ + QSize trayPanelSize = m_trayManager->suitableSize(position); + // 设置trayManagerWindow的大小和位置 + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { + setFixedSize(trayPanelSize.width(), rect.height()); + move(rect.topLeft()); + } else { + setFixedSize(rect.width(), trayPanelSize.height()); + move(rect.topLeft()); + } + + int panelSize = windowSize(); + QRect panelRect = rect; + switch(position) { + case Dock::Position::Left: + m_trayManager->move(width() - panelSize, 0); + panelRect.setWidth(panelSize); + panelRect.setHeight(trayPanelSize.height()); + break; + case Dock::Position::Top: + m_trayManager->move(0, height() - panelSize); + panelRect.setWidth(trayPanelSize.width()); + panelRect.setHeight(panelSize); + break; + case Dock::Position::Right: { + m_trayManager->move(0, 0); + panelRect.setWidth(panelSize); + panelRect.setHeight(trayPanelSize.height()); + break; + } + case Dock::Position::Bottom: { + m_trayManager->move(0, 0); + panelRect.setWidth(trayPanelSize.width()); + panelRect.setHeight(panelSize); + break; + } + } + + // 在从高效模式切换到时尚模式的时候,需要调用该函数来设置托盘区域的尺寸,在设置尺寸的时候会触发 + // 托盘区域的requestUpdate信号,WindowManager接收到requestUpdate会依次对每个顶层界面设置尺寸,此时又会触发该函数 + // 引起无限循环,因此,在设置尺寸的时候阻塞信号,防止进入死循环 + m_trayManager->blockSignals(true); + m_trayManager->setFixedSize(panelRect.size()); + m_trayManager->blockSignals(false); +} + +QSize TrayMainWindow::suitableSize() const +{ + return m_trayManager->suitableSize(); +} + +void TrayMainWindow::resetPanelGeometry() +{ + m_trayManager->setFixedSize(size()); + m_trayManager->move(0, 0); +} + +int TrayMainWindow::dockSpace() const +{ + return 0; +} + +void TrayMainWindow::updateRadius(int borderRadius) +{ + m_trayManager->updateBorderRadius(borderRadius); +} + +QSize TrayMainWindow::suitableSize(const Dock::Position &pos, const int &, const double &) const +{ + return m_trayManager->suitableSize(pos); +} + +void TrayMainWindow::initUI() +{ + m_trayManager->move(0, 0); +} + +void TrayMainWindow::initConnection() +{ + connect(m_trayManager, &TrayManagerWindow::requestUpdate, this, &TrayMainWindow::onRequestUpdate); +} + +void TrayMainWindow::onRequestUpdate() +{ + // 如果当前是高效模式,则无需发送信号 + if (displayMode() == Dock::DisplayMode::Efficient) + return; + + Q_EMIT requestUpdate(); +} diff --git a/frame/window/traymainwindow.h b/frame/window/traymainwindow.h new file mode 100644 index 000000000..ffd5fb168 --- /dev/null +++ b/frame/window/traymainwindow.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 TRAYMAINWINDOW_H +#define TRAYMAINWINDOW_H + +#include "constants.h" +#include "mainwindowbase.h" + +#include + +class TrayManagerWindow; +class MultiScreenWorker; + +DWIDGET_USE_NAMESPACE + +class TrayMainWindow : public MainWindowBase +{ + Q_OBJECT + +public: + TrayMainWindow(MultiScreenWorker *multiScreenWorker, QWidget *parent = Q_NULLPTR); + void setPosition(const Dock::Position &position) override; + TrayManagerWindow *trayManagerWindow() const; + + void setDisplayMode(const Dock::DisplayMode &displayMode) override; + DockWindowType windowType() const override; + void updateParentGeometry(const Dock::Position &position, const QRect &rect) override; + QSize suitableSize(const Dock::Position &pos, const int &, const double &) const override; + QSize suitableSize() const; + void resetPanelGeometry() override; + +protected: + int dockSpace() const override; + void updateRadius(int borderRadius) override; + +private: + void initUI(); + void initConnection(); + +private Q_SLOTS: + void onRequestUpdate(); + +private: + TrayManagerWindow *m_trayManager; + MultiScreenWorker *m_multiScreenWorker; +}; + +#endif // TRAYMAINWINDOW_H diff --git a/frame/window/traymanagerwindow.cpp b/frame/window/traymanagerwindow.cpp index 6a41748fa..dbf0b6baf 100644 --- a/frame/window/traymanagerwindow.cpp +++ b/frame/window/traymanagerwindow.cpp @@ -57,34 +57,44 @@ TrayManagerWindow::TrayManagerWindow(QWidget *parent) , m_quickIconWidget(new QuickPluginWindow(m_appPluginWidget)) , m_dateTimeWidget(new DateTimeDisplayer(m_appPluginDatetimeWidget)) , m_appPluginLayout(new QBoxLayout(QBoxLayout::Direction::LeftToRight, this)) - , m_appDatetimeLayout(new QBoxLayout(QBoxLayout::Direction::TopToBottom, this)) , m_mainLayout(new QBoxLayout(QBoxLayout::Direction::LeftToRight, this)) , m_trayView(new TrayGridView(this)) , m_model(new TrayModel(m_trayView, false, true)) , m_delegate(new TrayDelegate(m_trayView, m_trayView)) - , m_postion(Dock::Position::Bottom) + , m_position(Dock::Position::Bottom) , m_splitLine(new QLabel(m_appPluginDatetimeWidget)) + , m_dockInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this)) + , m_singleShow(false) + , m_borderRadius(0) { initUi(); initConnection(); setAcceptDrops(true); setMouseTracking(true); + + QMetaObject::invokeMethod(this, &TrayManagerWindow::updateLayout, Qt::QueuedConnection); } TrayManagerWindow::~TrayManagerWindow() { } +void TrayManagerWindow::updateBorderRadius(int borderRadius) +{ + m_borderRadius = borderRadius; + update(); +} + void TrayManagerWindow::updateLayout() { - bool showSingle = true; - if (m_postion == Dock::Position::Top || m_postion == Dock::Position::Bottom) - showSingle = (topLevelWidget()->height() <= CRITLCALHEIGHT); + bool lastIsSingle = m_singleShow; + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + m_singleShow = (height() <= CRITLCALHEIGHT); + else + m_singleShow = true; - QBoxLayout::Direction lastDirection = m_appDatetimeLayout->direction(); - - if (showSingle) + if (m_singleShow) resetSingleDirection(); else resetMultiDirection(); @@ -94,16 +104,16 @@ void TrayManagerWindow::updateLayout() Q_EMIT m_delegate->sizeHintChanged(m_model->index(0, 0)); // 当插件区域从单行变成两行或者两行变成单行的时候,发送该信号,通知外部重新调整区域大小 - if (lastDirection != m_appDatetimeLayout->direction()) + if (lastIsSingle != m_singleShow) Q_EMIT requestUpdate(); } void TrayManagerWindow::setPositon(Dock::Position position) { - if (m_postion == position) + if (m_position == position) return; - m_postion = position; + m_position = position; if (position == Dock::Position::Top || position == Dock::Position::Bottom) m_trayView->setOrientation(QListView::Flow::LeftToRight, false); @@ -120,51 +130,62 @@ void TrayManagerWindow::setPositon(Dock::Position position) m_quickIconWidget->setPositon(position); m_dateTimeWidget->setPositon(position); m_systemPluginWidget->setPositon(position); + + updateLayout(); } -int TrayManagerWindow::appDatetimeSize() +int TrayManagerWindow::appDatetimeSize(const Dock::Position &position) const { - if (m_postion == Dock::Position::Top || m_postion == Dock::Position::Bottom) { - // 如果是一行 - if (m_appDatetimeLayout->direction() == QBoxLayout::Direction::LeftToRight) { - return m_trayView->suitableSize().width() + m_quickIconWidget->suitableSize().width() - + m_dateTimeWidget->suitableSize().width() + m_appDatetimeLayout->spacing(); + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { + bool showSingle = m_singleShow; + // 正在从左右切换到上下(m_position当前显示的位置,还未切换),此时根据托盘区域的尺寸来决定显示一行还是两行 + if (m_position == Dock::Position::Left || m_position == Dock::Position::Right) { + showSingle = m_dockInter->windowSizeFashion() < CRITLCALHEIGHT; + } + + // 如果是一行或者是在切换位置(从左右切换到上下) + if (showSingle) { + return m_trayView->suitableSize(position).width() + m_quickIconWidget->suitableSize(position).width() + + m_dateTimeWidget->suitableSize(position).width() + 4; } //如果是两行 - int topWidth = m_trayView->suitableSize().width() + m_appDatetimeLayout->spacing() + m_quickIconWidget->width(); - int bottomWidth = m_dateTimeWidget->suitableSize().width(); + int topWidth = m_trayView->suitableSize(position).width() + m_quickIconWidget->suitableSize(position).width(); + int bottomWidth = m_dateTimeWidget->suitableSize(position).width(); return qMax(topWidth, bottomWidth); } - int trayHeight = m_trayView->suitableSize().height(); - QMargins m = m_appDatetimeLayout->contentsMargins(); - int traypluginHeight = trayHeight + m_quickIconWidget->suitableSize().height() + m.top() + m.bottom() + m_appPluginLayout->spacing(); - return traypluginHeight + m_appDatetimeLayout->spacing() + m_dateTimeWidget->suitableSize().height() + 10; + int trayHeight = m_trayView->suitableSize(position).height(); + int traypluginHeight = trayHeight + m_quickIconWidget->suitableSize(position).height() + m_appPluginLayout->spacing(); + return traypluginHeight + m_dateTimeWidget->suitableSize(position).height() + 10; } -QSize TrayManagerWindow::suitableSize() +QSize TrayManagerWindow::suitableSize() const +{ + return suitableSize(m_position); +} + +QSize TrayManagerWindow::suitableSize(const Dock::Position &position) const { QMargins m = m_mainLayout->contentsMargins(); - if (m_postion == Dock::Position::Top || m_postion == Dock::Position::Bottom) { - return QSize(appDatetimeSize() + m_appDatetimeLayout->spacing() + - m_systemPluginWidget->suitableSize().width() + m_mainLayout->spacing() + + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { + return QSize(appDatetimeSize(position) + + m_systemPluginWidget->suitableSize(position).width() + m_mainLayout->spacing() + m.left() + m.right(), QWIDGETSIZE_MAX); } - return QSize(QWIDGETSIZE_MAX, appDatetimeSize() + m_appDatetimeLayout->spacing() + - m_systemPluginWidget->suitableSize().height() + m_mainLayout->spacing() + + return QSize(QWIDGETSIZE_MAX, appDatetimeSize(position) + + m_systemPluginWidget->suitableSize(position).height() + m_mainLayout->spacing() + m.top() + m.bottom()); } // 用于返回需要绘制的圆形区域 QPainterPath TrayManagerWindow::roundedPaths() { - int topLevelRadius = qApp->property("EffectBorderRadius").toInt(); QMargins mainMargin = m_mainLayout->contentsMargins(); - int radius = topLevelRadius - mainMargin.top(); + int radius = m_borderRadius - mainMargin.top(); QPainterPath path; - if ((m_postion == Dock::Position::Top || m_postion == Dock::Position::Bottom) - && (m_appDatetimeLayout->direction() == QBoxLayout::Direction::LeftToRight)) { + if ((m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + && m_singleShow) { // 如果是上下方向,且只有一行 // 计算托盘和快捷插件区域 QPoint pointPlugin(mainMargin.left(), mainMargin.top()); @@ -220,13 +241,6 @@ void TrayManagerWindow::initUi() m_appPluginLayout->addWidget(m_trayView); m_appPluginLayout->addWidget(m_quickIconWidget); - m_appPluginDatetimeWidget->setLayout(m_appDatetimeLayout); - m_appDatetimeLayout->setContentsMargins(0, 0, 0, 0); - m_appDatetimeLayout->setSpacing(0); - m_appDatetimeLayout->addWidget(m_appPluginWidget); - m_appDatetimeLayout->addWidget(m_splitLine); - m_appDatetimeLayout->addWidget(m_dateTimeWidget); - setLayout(m_mainLayout); // 通用情况下,设置边距和间距都为7 m_mainLayout->setContentsMargins(CONTENTSPACE, CONTENTSPACE, CONTENTSPACE, CONTENTSPACE); @@ -253,7 +267,7 @@ void TrayManagerWindow::initConnection() connect(m_quickIconWidget, &QuickPluginWindow::itemCountChanged, this, [ this ] { // 当插件数量发生变化的时候,需要调整尺寸 m_quickIconWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); - if (m_postion == Dock::Position::Top || m_postion == Dock::Position::Bottom) + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) m_quickIconWidget->setFixedWidth(m_quickIconWidget->suitableSize().width()); else m_quickIconWidget->setFixedHeight(m_quickIconWidget->suitableSize().height()); @@ -264,7 +278,7 @@ void TrayManagerWindow::initConnection() connect(m_systemPluginWidget, &SystemPluginWindow::itemChanged, this, [ this ] { // 当系统插件发生变化的时候,同样需要调整尺寸 m_systemPluginWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); - if (m_postion == Dock::Position::Top || m_postion == Dock::Position::Bottom) + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) m_systemPluginWidget->setFixedWidth(m_systemPluginWidget->suitableSize().width()); else m_systemPluginWidget->setFixedHeight(m_systemPluginWidget->suitableSize().height()); @@ -310,12 +324,13 @@ void TrayManagerWindow::resetChildWidgetSize() count++; } - switch (m_postion) { + switch (m_position) { case Dock::Position::Top: case Dock::Position::Bottom: { int trayWidth = m_trayView->suitableSize().width(); + int appDateTimeWidth = appDatetimeSize(m_position); QMargins m = m_appPluginLayout->contentsMargins(); - if (m_appDatetimeLayout->direction() == QBoxLayout::Direction::LeftToRight) { + if (m_singleShow) { // 单行显示 int trayHeight = m_appPluginDatetimeWidget->height() - m.top() - m.bottom(); m_trayView->setFixedSize(trayWidth, trayHeight); @@ -324,27 +339,46 @@ void TrayManagerWindow::resetChildWidgetSize() m_dateTimeWidget->setFixedSize(m_dateTimeWidget->suitableSize().width(), trayHeight); // 设置右侧的电源按钮的尺寸 m_systemPluginWidget->setFixedSize(m_systemPluginWidget->suitableSize()); - m_mainLayout->setContentsMargins(4, 4, 4 ,4); - m_mainLayout->setSpacing(4); - m_appDatetimeLayout->setSpacing(4); + // 如果顶层窗体的高度为0,则直接让其间距为0,否则就会出现隐藏模式下,有8个像素的高度依然显示 + int space = topLevelWidget()->height() == 0 ? 0 : 4; + m_mainLayout->setContentsMargins(space, space, space ,space); + m_mainLayout->setSpacing(space); + // 单行显示需要重新设置插件和时间日期的位置,不显示分割线 + m_splitLine->setVisible(false); + m_appPluginWidget->move(0, 0); + m_dateTimeWidget->move(m_appPluginWidget->x() + m_appPluginWidget->width() + 4, m_appPluginWidget->y()); } else { // 多行显示 + m_quickIconWidget->setFixedSize(m_quickIconWidget->suitableSize()); int trayHeight = m_appPluginDatetimeWidget->height() / 2 + 4 - m.top() - m.bottom(); m_trayView->setFixedSize(trayWidth, trayHeight); - m_quickIconWidget->setFixedSize(m_quickIconWidget->suitableSize().width(), trayHeight); - m_appPluginWidget->setFixedSize(trayWidth + m_quickIconWidget->suitableSize().width(), m_appPluginDatetimeWidget->height() / 2 + 4); + m_appPluginWidget->setFixedSize(trayWidth + m_quickIconWidget->suitableSize().width(), trayHeight); // 因为是两行,所以对于时间控件的尺寸,只能设置最小值 int dateTimeWidth = qMax(m_appPluginWidget->width(), m_dateTimeWidget->suitableSize().width()); - m_dateTimeWidget->setMinimumSize(dateTimeWidth, QWIDGETSIZE_MAX); + int dateTimeHeight = m_appPluginDatetimeWidget->height() - - m.top() - m.bottom() - trayHeight; + m_dateTimeWidget->setFixedSize(dateTimeWidth, dateTimeHeight); m_systemPluginWidget->setFixedSize(m_systemPluginWidget->suitableSize()); int contentSpace = qMin(MAXDIFF, qMax(height() - MINHIGHT, 0)) + MINSPACE; m_mainLayout->setContentsMargins(contentSpace, contentSpace, contentSpace, contentSpace); - m_appDatetimeLayout->setSpacing(0); m_mainLayout->setSpacing(contentSpace); + + // 调整插件和日期窗体的位置显示,这里没有用到布局,是因为在调整任务栏位置的时候, + // 随着布局方向的改变,显示有很大的问题 + m_splitLine->setFixedWidth(appDateTimeWidth); + m_splitLine->setVisible(true); + if (m_position == Dock::Position::Bottom) { + m_appPluginWidget->move(0, 0); + m_splitLine->move(0, m_appPluginWidget->y() + m_appPluginWidget->height()); + m_dateTimeWidget->move(0, m_appPluginWidget->y() + m_appPluginWidget->height() + m_splitLine->height()); + } else { + m_dateTimeWidget->move(0, 0); + m_splitLine->move(0, m_dateTimeWidget->y() + m_dateTimeWidget->height()); + m_appPluginWidget->move(0, m_dateTimeWidget->y() + m_dateTimeWidget->height() + m_splitLine->height()); + } } QMargins margin = m_mainLayout->contentsMargins(); int appDateHeight = height() - margin.top() - margin.bottom(); - m_appPluginDatetimeWidget->setFixedSize(appDatetimeSize(), appDateHeight); + m_appPluginDatetimeWidget->setFixedSize(appDateTimeWidth, appDateHeight); break; } case Dock::Position::Left: @@ -361,13 +395,19 @@ void TrayManagerWindow::resetChildWidgetSize() m_appPluginWidget->setFixedSize(sizeWidth, trayHeight + quickAreaHeight); m_systemPluginWidget->setFixedSize(m_systemPluginWidget->suitableSize()); - int contentSpace = qMin(MAXDIFF, qMax(width() - MINHIGHT, 0)) + MINSPACE; + int contentSpace = (qMin(MAXDIFF, qMax(width() - MINHIGHT, 0)) + MINSPACE); m_mainLayout->setContentsMargins(contentSpace, contentSpace, contentSpace, contentSpace); - m_appDatetimeLayout->setSpacing(0); m_mainLayout->setSpacing(contentSpace); int appDateWidth = width() - (contentSpace * 2); - m_appPluginDatetimeWidget->setFixedSize(appDateWidth, appDatetimeSize()); + m_appPluginDatetimeWidget->setFixedSize(appDateWidth, appDatetimeSize(m_position)); + + // 调整各个部件的位置 + m_appPluginWidget->move(0, 0); + m_splitLine->setFixedWidth(width()); + m_splitLine->setVisible(true); + m_splitLine->move(0, m_appPluginWidget->y() + m_appPluginWidget->height()); + m_dateTimeWidget->move(0, m_appPluginWidget->y() + m_appPluginWidget->height() + m_splitLine->height()); break; } } @@ -375,22 +415,18 @@ void TrayManagerWindow::resetChildWidgetSize() void TrayManagerWindow::resetSingleDirection() { - switch (m_postion) { + switch (m_position) { case Dock::Position::Top: case Dock::Position::Bottom: { m_appPluginLayout->setDirection(QBoxLayout::Direction::LeftToRight); // 应用和时间在一行显示 - m_appDatetimeLayout->setSpacing(10); - m_appDatetimeLayout->setDirection(QBoxLayout::Direction::LeftToRight); m_mainLayout->setDirection(QBoxLayout::Direction::LeftToRight); m_splitLine->hide(); break; } case Dock::Position::Left: case Dock::Position::Right:{ - m_appDatetimeLayout->setSpacing(0); m_appPluginLayout->setDirection(QBoxLayout::Direction::TopToBottom); - m_appDatetimeLayout->setDirection(QBoxLayout::Direction::TopToBottom); m_mainLayout->setDirection(QBoxLayout::Direction::TopToBottom); m_splitLine->show(); break; @@ -401,19 +437,10 @@ void TrayManagerWindow::resetSingleDirection() void TrayManagerWindow::resetMultiDirection() { - m_appDatetimeLayout->setSpacing(0); - switch (m_postion) { - case Dock::Position::Top: { - m_appPluginLayout->setDirection(QBoxLayout::Direction::LeftToRight); - m_appDatetimeLayout->setDirection(QBoxLayout::Direction::BottomToTop); - m_mainLayout->setDirection(QBoxLayout::Direction::LeftToRight); - m_splitLine->show(); - m_dateTimeWidget->setOneRow(false); - break; - } + switch (m_position) { + case Dock::Position::Top: case Dock::Position::Bottom: { m_appPluginLayout->setDirection(QBoxLayout::Direction::LeftToRight); - m_appDatetimeLayout->setDirection(QBoxLayout::Direction::TopToBottom); m_mainLayout->setDirection(QBoxLayout::Direction::LeftToRight); m_splitLine->show(); m_dateTimeWidget->setOneRow(false); @@ -422,7 +449,6 @@ void TrayManagerWindow::resetMultiDirection() case Dock::Position::Left: case Dock::Position::Right: { m_appPluginLayout->setDirection(QBoxLayout::Direction::TopToBottom); - m_appDatetimeLayout->setDirection(QBoxLayout::Direction::TopToBottom); m_mainLayout->setDirection(QBoxLayout::Direction::TopToBottom); m_splitLine->hide(); m_dateTimeWidget->setOneRow(true); diff --git a/frame/window/traymanagerwindow.h b/frame/window/traymanagerwindow.h index 20650a3ed..e1ff560e6 100644 --- a/frame/window/traymanagerwindow.h +++ b/frame/window/traymanagerwindow.h @@ -22,6 +22,7 @@ #define TRAYMANAGERWINDOW_H #include "constants.h" +#include "dbusutil.h" #include @@ -43,6 +44,7 @@ class SystemPluginWindow; class QLabel; class QDropEvent; class DateTimeDisplayer; +class QPainterPath; class TrayManagerWindow : public QWidget { @@ -52,9 +54,11 @@ public: explicit TrayManagerWindow(QWidget *parent = nullptr); ~TrayManagerWindow() override; + void updateBorderRadius(int borderRadius); void updateLayout(); void setPositon(Dock::Position position); - QSize suitableSize(); + QSize suitableSize() const; + QSize suitableSize(const Dock::Position &position) const; Q_SIGNALS: void requestUpdate(); @@ -76,7 +80,7 @@ private: void resetSingleDirection(); QColor maskColor(uint8_t alpha) const; - int appDatetimeSize(); + int appDatetimeSize(const Dock::Position &position) const; QPainterPath roundedPaths(); private: @@ -86,13 +90,15 @@ private: QuickPluginWindow *m_quickIconWidget; DateTimeDisplayer *m_dateTimeWidget; QBoxLayout *m_appPluginLayout; - QBoxLayout *m_appDatetimeLayout; QBoxLayout *m_mainLayout; TrayGridView *m_trayView; TrayModel *m_model; TrayDelegate *m_delegate; - Dock::Position m_postion; + Dock::Position m_position; QLabel *m_splitLine; + DockInter *m_dockInter; + bool m_singleShow; // 用于记录当前日期时间和插件区域是显示一行还是显示多行 + int m_borderRadius; // 圆角的值 }; #endif // PLUGINWINDOW_H diff --git a/frame/window/windowmanager.cpp b/frame/window/windowmanager.cpp new file mode 100644 index 000000000..708179cba --- /dev/null +++ b/frame/window/windowmanager.cpp @@ -0,0 +1,810 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 "mainwindow.h" +#include "windowmanager.h" +#include "traymainwindow.h" +#include "multiscreenworker.h" +#include "menuworker.h" +#include "dockitemmanager.h" +#include "dockscreen.h" +#include "displaymanager.h" +#include "proxyplugincontroller.h" + +#include +#include + +#include +#include +#include + +#include +#include + +DGUI_USE_NAMESPACE + +#define SNI_WATCHER_SERVICE "org.kde.StatusNotifierWatcher" +#define SNI_WATCHER_PATH "/StatusNotifierWatcher" + +#define DOCKSCREEN_INS DockScreen::instance() +#define DIS_INS DisplayManager::instance() + +using org::kde::StatusNotifierWatcher; + +WindowManager::WindowManager(MultiScreenWorker *multiScreenWorker, QObject *parent) + : QObject(parent) + , m_multiScreenWorker(multiScreenWorker) + , m_displayMode(Dock::DisplayMode::Efficient) + , m_position(Dock::Position::Bottom) + , m_dbusDaemonInterface(QDBusConnection::sessionBus().interface()) + , m_sniWatcher(new StatusNotifierWatcher(SNI_WATCHER_SERVICE, SNI_WATCHER_PATH, QDBusConnection::sessionBus(), this)) +{ + initSNIHost(); + initConnection(); + initMember(); +} + +WindowManager::~WindowManager() +{ +} + +void WindowManager::addWindow(MainWindowBase *window) +{ + connect(window, &MainWindowBase::requestUpdate, this, &WindowManager::onRequestUpdate); + + window->setPosition(m_multiScreenWorker->position()); + window->setDisplayMode(m_multiScreenWorker->displayMode()); + window->setOrder(m_topWindows.size()); + + m_topWindows << window; +} + +void WindowManager::launch() +{ + if (!qApp->property("CANSHOW").toBool()) + return; + + const QString ¤tScreen = DOCKSCREEN_INS->current(); + if (m_multiScreenWorker->hideMode() == HideMode::KeepShowing) { + onPlayAnimation(currentScreen, m_multiScreenWorker->position(), Dock::AniAction::Show); + } else if (m_multiScreenWorker->hideMode() == HideMode::KeepHidden) { + qApp->setProperty(PROP_HIDE_STATE, HideState::Hide); + onUpdateDockGeometry(HideMode::KeepHidden); + } else if (m_multiScreenWorker->hideMode() == HideMode::SmartHide) { + switch(m_multiScreenWorker->hideState()) { + case HideState::Show: + onPlayAnimation(currentScreen, m_multiScreenWorker->position(), Dock::AniAction::Show); + break; + case HideState::Hide: + onPlayAnimation(currentScreen, m_multiScreenWorker->position(), Dock::AniAction::Hide); + break; + default: + break; + } + + qApp->setProperty(PROP_HIDE_STATE, m_multiScreenWorker->hideState()); + } + + QMetaObject::invokeMethod(this, [ this ] { + for (MainWindowBase *mainWindow : m_topWindows) + mainWindow->setDisplayMode(m_multiScreenWorker->displayMode()); + }, Qt::QueuedConnection); +} + +void WindowManager::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(); + }); +} + +/** + * @brief MainWindow::callShow + * 此方法是被外部进程通过DBus调用的。 + * @note 当任务栏以-r参数启动时,其不会显示界面,需要在外部通过DBus调用此接口之后才会显示界面, + * 这里是以前为了优化任务栏的启动速度做的处理,当任务栏启动时,此时窗管进程可能还未启动完全, + * 部分设置未初始化完等,导致任务栏显示的界面异常,所以留下此接口,被startdde延后调用 + */ + +void WindowManager::callShow() +{ + static bool flag = false; + if (flag) { + return; + } + flag = true; + + qApp->setProperty("CANSHOW", true); + + launch(); + + // 预留200ms提供给窗口初始化再通知startdde,不影响启动速度 + QTimer::singleShot(200, this, &WindowManager::RegisterDdeSession); +} + +/** 调整任务栏的大小,这个接口提供给dbus使用,一般是控制中心来调用 + * @brief WindowManager::resizeDock + * @param offset + * @param dragging + */ +void WindowManager::resizeDock(int offset, bool dragging) +{ + QScreen *screen = DIS_INS->screen(DOCKSCREEN_INS->current()); + if (!screen) + return; + + m_multiScreenWorker->setStates(MultiScreenWorker::DockIsDraging, dragging); + + int dockSize = qBound(DOCK_MIN_SIZE, offset, DOCK_MAX_SIZE); + for (MainWindowBase *mainWindow : m_topWindows) { + QRect windowRect = mainWindow->getDockGeometry(screen, m_multiScreenWorker->position(), m_multiScreenWorker->displayMode(), Dock::HideState::Hide); + QRect newWindowRect; + switch (m_multiScreenWorker->position()) { + case Top: { + newWindowRect.setX(windowRect.x()); + newWindowRect.setY(windowRect.y()); + newWindowRect.setWidth(windowRect.width()); + newWindowRect.setHeight(dockSize); + break; + } + case Bottom: { + newWindowRect.setX(windowRect.x()); + newWindowRect.setY(windowRect.y() + windowRect.height() - dockSize); + newWindowRect.setWidth(windowRect.width()); + newWindowRect.setHeight(dockSize); + break; + } + case Left: { + newWindowRect.setX(windowRect.x()); + newWindowRect.setY(windowRect.y()); + newWindowRect.setWidth(dockSize); + newWindowRect.setHeight(windowRect.height()); + break; + } + case Right: { + newWindowRect.setX(windowRect.x() + windowRect.width() - dockSize); + newWindowRect.setY(windowRect.y()); + newWindowRect.setWidth(dockSize); + newWindowRect.setHeight(windowRect.height()); + break; + } + } + + // 更新界面大小 + mainWindow->blockSignals(true); + mainWindow->setFixedSize(newWindowRect.size()); + mainWindow->resetPanelGeometry(); + mainWindow->move(newWindowRect.topLeft()); + mainWindow->blockSignals(false); + } + + m_multiScreenWorker->updateDaemonDockSize(dockSize); +} + +/** 获取任务栏的实际大小,这个接口用于获取任务栏的尺寸返回给dbus接口 + * @brief WindowManager::geometry + * @return 任务栏的实际尺寸和位置信息 + */ +QRect WindowManager::geometry() const +{ + int x = 0; + int y = 0; + int width = 0; + int height = 0; + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + for (int i = 0; i < m_topWindows.size(); i++) { + MainWindowBase *mainWindow = m_topWindows[i]; + if (!mainWindow->isVisible()) + continue; + + QRect windowRect = mainWindow->rect(); + if (i == 0 || x > windowRect.x()) + x = windowRect.x(); + if (i == 0) { + y = windowRect.y(); + height = windowRect.height(); + } + width += windowRect.width() + mainWindow->dockSpace(); + } + + return QRect(x, y, width, height); + } + + for (int i = 0; i < m_topWindows.size(); i++) { + MainWindowBase *mainWindow = m_topWindows[i]; + if (!mainWindow->isVisible()) + continue; + + QRect windowRect = mainWindow->rect(); + if (i == 0 || y > windowRect.y()) + y = windowRect.y(); + + if (i == 0) { + x = windowRect.x(); + width = windowRect.width(); + } + + height += windowRect.height() + mainWindow->dockSpace(); + } + + return QRect(x, y, width, height); +} + +void WindowManager::onUpdateDockGeometry(const Dock::HideMode &hideMode) +{ + Dock::HideState hideState; + if (hideMode == HideMode::KeepShowing || (hideMode == HideMode::SmartHide && m_multiScreenWorker->hideState() == HideState::Show)) + hideState = Dock::HideState::Show; + else + hideState = Dock::HideState::Hide; + + updateMainGeometry(hideState); +} + +void WindowManager::onPositionChanged(const Dock::Position &position) +{ + Position lastPos = m_position; + if (lastPos == position) + return; + + m_position = position; + // 调用设置位置,一会根据需要放到实际的位置 + for (MainWindowBase *mainWindow : m_topWindows) + mainWindow->setPosition(position); + + // 在改变位置后,需要根据当前任务栏是隐藏还是显示,来调整左右两侧区域的大小 + onUpdateDockGeometry(HideMode::KeepHidden); +} + +void WindowManager::onDisplayModeChanged(const Dock::DisplayMode &displayMode) +{ + m_displayMode = displayMode; + + DockItem::setDockDisplayMode(m_displayMode); + qApp->setProperty(PROP_DISPLAY_MODE, QVariant::fromValue(displayMode)); + + for (MainWindowBase *mainWindow : m_topWindows) + mainWindow->setDisplayMode(m_displayMode); + + onUpdateDockGeometry(m_multiScreenWorker->hideMode()); +} + +void WindowManager::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); + } +} + +void WindowManager::showAniFinish() +{ + qApp->setProperty(PROP_HIDE_STATE, HideState::Show); + + // 通知后端更新区域 + onRequestUpdateFrontendGeometry(); + onRequestNotifyWindowManager(); +} + +void WindowManager::hideAniFinish() +{ + DockItem::setDockPosition(m_position); + qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position)); + qApp->setProperty(PROP_HIDE_STATE, HideState::Hide); + // 通知后端更新区域 + onRequestUpdateFrontendGeometry(); + onRequestNotifyWindowManager(); +} + +/**获取整个任务栏区域的位置和尺寸的信息,用于提供给后端设置位置等信息 + * @brief WindowManager::getDockGeometry + * @param withoutScale + * @return + */ +QRect WindowManager::getDockGeometry(bool withoutScale) const +{ + QScreen *screen = DIS_INS->screen(DOCKSCREEN_INS->current()); + if (!screen) + return QRect(); + + int x = 0; + int y = 0; + int width = 0; + int height = 0; + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + for (int i = 0; i < m_topWindows.size(); i++) { + MainWindowBase *mainWindow = m_topWindows[i]; + if (!mainWindow->isVisible()) + continue; + + QRect windowRect = mainWindow->getDockGeometry(screen, m_position, m_displayMode, Dock::HideState::Show, withoutScale); + if (i == 0 || x > windowRect.x()) + x = windowRect.x(); + + if (i == 0) { + y = windowRect.y(); + height = windowRect.height(); + } + width += windowRect.width() + mainWindow->dockSpace(); + } + } else { + for (int i = 0; i < m_topWindows.size(); i++) { + MainWindowBase *mainWindow = m_topWindows[i]; + if (!mainWindow->isVisible()) + continue; + + QRect windowRect = mainWindow->getDockGeometry(screen, m_position, m_displayMode, Dock::HideState::Show, withoutScale); + if (i == 0 || y > windowRect.y()) + y = windowRect.y(); + + if (i == 0) { + y = windowRect.y(); + width = windowRect.width(); + } + height += windowRect.height() + mainWindow->dockSpace(); + } + } + + return QRect(x, y, width, height); +} + +void WindowManager::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(); + } +} + +void WindowManager::initConnection() +{ + connect(m_dbusDaemonInterface, &QDBusConnectionInterface::serviceOwnerChanged, this, &WindowManager::onDbusNameOwnerChanged); + + connect(m_multiScreenWorker, &MultiScreenWorker::requestUpdateDockGeometry, this, &WindowManager::onUpdateDockGeometry); + connect(m_multiScreenWorker, &MultiScreenWorker::positionChanged, this, &WindowManager::onPositionChanged); + connect(m_multiScreenWorker, &MultiScreenWorker::displayModeChanged, this, &WindowManager::onDisplayModeChanged); + connect(m_multiScreenWorker, &MultiScreenWorker::requestPlayAnimation, this, &WindowManager::onPlayAnimation); + connect(m_multiScreenWorker, &MultiScreenWorker::requestChangeDockPosition, this, &WindowManager::onChangeDockPosition); + connect(m_multiScreenWorker, &MultiScreenWorker::requestUpdateFrontendGeometry, this, &WindowManager::onRequestUpdateFrontendGeometry); + connect(m_multiScreenWorker, &MultiScreenWorker::requestNotifyWindowManager, this, &WindowManager::onRequestNotifyWindowManager); + connect(m_multiScreenWorker, &MultiScreenWorker::requestUpdateFrontendGeometry, DockItemManager::instance(), &DockItemManager::requestUpdateDockItem); + connect(DockItemManager::instance(), &DockItemManager::requestWindowAutoHide, m_multiScreenWorker, &MultiScreenWorker::onAutoHideChanged); +} + +void WindowManager::initSNIHost() +{ + 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 WindowManager::initMember() +{ + m_displayMode = m_multiScreenWorker->displayMode(); + m_position = m_multiScreenWorker->position(); +} + +// 更新任务栏的位置和尺寸的信息 +void WindowManager::updateMainGeometry(const Dock::HideState &hideState) +{ + QScreen *screen = DIS_INS->screen(DOCKSCREEN_INS->current()); + if (!screen) + return; + + for (MainWindowBase *mainWindow : m_topWindows) { + QRect windowRect = mainWindow->getDockGeometry(screen, m_multiScreenWorker->position(), m_multiScreenWorker->displayMode(), hideState); + mainWindow->updateParentGeometry(m_position, windowRect); + } + + // 在切换模式的时候,需要根据实际当前是隐藏还是显示来记录当前任务栏是隐藏还是显示,MainPanelWindow会根据这个状态来决定怎么获取图标的尺寸, + // 如果不加上这一行,那么鼠标在唤醒任务栏的时候,左侧区域会有显示问题 + qApp->setProperty(PROP_HIDE_STATE, hideState); +} + +void WindowManager::onPlayAnimation(const QString &screenName, const Dock::Position &pos, Dock::AniAction act, bool containMouse, bool updatePos) +{ + // 如果containMouse= true,则需要计算鼠标是否包含在任务栏的位置, 如果鼠标在任务栏内部,则无需执行动画,这种情况一般用于执行隐藏模式发生变化的时候 + if (containMouse) { + QRect dockGeometry = getDockGeometry(false); + if (dockGeometry.contains(QCursor::pos())) + return; + } + + if (act == Dock::AniAction::Show) { + for (MainWindowBase *mainWindow : m_topWindows) { + if (mainWindow->windowType() != MainWindowBase::DockWindowType::MainWindow) + continue; + + // 如果请求显示的动画,且当前任务栏已经显示,则不继续执行动画 + if (mainWindow->width() > 0 && mainWindow->height() > 0) + return; + } + } + + QScreen *screen = DIS_INS->screen(screenName); + if (!m_multiScreenWorker->testState(MultiScreenWorker::RunState::AutoHide) || qApp->property("DRAG_STATE").toBool() + || m_multiScreenWorker->testState(MultiScreenWorker::RunState::ChangePositionAnimationStart) + || m_multiScreenWorker->testState(MultiScreenWorker::RunState::HideAnimationStart) + || m_multiScreenWorker->testState(MultiScreenWorker::RunState::ShowAnimationStart) + || !screen) + return; + + QParallelAnimationGroup *group = createAnimationGroup(act, screenName, pos); + if (!group) + return; + + switch (act) { + case Dock::AniAction::Show: + m_multiScreenWorker->setStates(MultiScreenWorker::ShowAnimationStart); + break; + case Dock::AniAction::Hide: + m_multiScreenWorker->setStates(MultiScreenWorker::HideAnimationStart); + } + + connect(group, &QParallelAnimationGroup::finished, this, [ = ] { + switch (act) { + case Dock::AniAction::Show: + showAniFinish(); + if (updatePos) + onPositionChanged(m_multiScreenWorker->position()); + m_multiScreenWorker->setStates(MultiScreenWorker::ShowAnimationStart, false); + break; + case Dock::AniAction::Hide: + hideAniFinish(); + if (updatePos) + onPositionChanged(m_multiScreenWorker->position()); + m_multiScreenWorker->setStates(MultiScreenWorker::HideAnimationStart, false); + break; + } + }); + + group->stop(); + group->start(QVariantAnimation::DeleteWhenStopped); +} + +/**创建动画,在时尚模式先同时创建左区域和右区域的动画 + * @brief WindowManager::createAnimationGroup + * @param aniAction 显示动画还是隐藏动画 + * @param screenName 执行动画的屏幕 + * @param position 执行动画的位置(上下左右) + * @return 要执行的动画组(左右侧区域同时执行的动画组) + */ +QParallelAnimationGroup *WindowManager::createAnimationGroup(const Dock::AniAction &aniAction, const QString &screenName, const Dock::Position &position) const +{ + QScreen *screen = DIS_INS->screen(screenName); + if (!screen) + return nullptr; + + bool stopAnimation = false; + QList animations; + for (MainWindowBase *mainWindow : m_topWindows) { + if (!mainWindow->isVisible()) + continue; + + QVariantAnimation *ani = mainWindow->createAnimation(screen, position, aniAction); + if (!ani) { + stopAnimation = true; + continue; + } + + animations << ani; + } + + if (stopAnimation) { + qDeleteAll(animations.begin(), animations.end()); + return nullptr; + } + + QParallelAnimationGroup *aniGroup = new QParallelAnimationGroup; + for (QVariantAnimation *ani : animations) { + ani->setParent(aniGroup); + aniGroup->addAnimation(ani); + } + + return aniGroup; +} + +void WindowManager::onChangeDockPosition(QString fromScreen, QString toScreen, const Dock::Position &fromPos, const Dock::Position &toPos) +{ + QList animations; + // 获取隐藏的动作 + QParallelAnimationGroup *hideGroup = createAnimationGroup(Dock::AniAction::Hide, fromScreen, fromPos); + if (hideGroup) { + connect(hideGroup, &QParallelAnimationGroup::finished, this, [ = ] { + // 在隐藏动画结束的时候,开始设置位置信息 + onPositionChanged(m_multiScreenWorker->position()); + DockItem::setDockPosition(m_multiScreenWorker->position()); + qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_multiScreenWorker->position())); + }); + animations << hideGroup; + } + // 获取显示的动作 + QParallelAnimationGroup *showGroup = createAnimationGroup(Dock::AniAction::Show, toScreen, toPos); + if (showGroup) + animations << showGroup; + + if (animations.size() == 0) + return; + + m_multiScreenWorker->setStates(MultiScreenWorker::ChangePositionAnimationStart); + + QSequentialAnimationGroup *group = new QSequentialAnimationGroup; + connect(group, &QVariantAnimation::finished, this, [ = ] { + // 结束之后需要根据确定需要再隐藏 + showAniFinish(); + m_multiScreenWorker->setStates(MultiScreenWorker::ChangePositionAnimationStart, false); + }); + + for (QParallelAnimationGroup *ani : animations) { + ani->setParent(group); + group->addAnimation(ani); + } + + group->start(QVariantAnimation::DeleteWhenStopped); +} + +void WindowManager::onRequestUpdateFrontendGeometry() +{ + QRect rect = getDockGeometry(false); + // 向com.deepin.dde.daemon.Dock的SetFrontendWindowRect接口设置区域时,此区域的高度或宽度不能为0,否则会导致其HideState属性循环切换,造成任务栏循环显示或隐藏 + if (rect.width() == 0 || rect.height() == 0) + return; + + DockInter dockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus()); + dockInter.SetFrontendWindowRect(int(rect.x()), int(rect.y()), uint(rect.width()), uint(rect.height())); +} + +void WindowManager::onRequestNotifyWindowManager() +{ + static QRect lastRect = QRect(); + static int lastScreenWidth = 0; + static int lastScreenHeight = 0; + + // 从列表中查找主窗口 + MainWindowBase *mainWindow = nullptr; + for (MainWindowBase *window : m_topWindows) { + if (window->windowType() != MainWindowBase::DockWindowType::MainWindow) + continue; + + mainWindow = window; + break; + } + + if (!mainWindow) + return; + + /* 在非主屏或非一直显示状态时,清除任务栏区域,不挤占应用 */ + if ((!DIS_INS->isCopyMode() && DOCKSCREEN_INS->current() != DOCKSCREEN_INS->primary()) || m_multiScreenWorker->hideMode() != HideMode::KeepShowing) { + lastRect = QRect(); + + if (Utils::IS_WAYLAND_DISPLAY) { + QList varList; + varList.append(0);//dock位置 + varList.append(0);//dock高度/宽度 + varList.append(0);//start值 + varList.append(0);//end值 + + // 此处只需获取左侧主窗口部分即可 + QPlatformWindow *windowHandle = mainWindow->windowHandle()->handle(); + if (windowHandle) + QGuiApplication::platformNativeInterface()->setWindowProperty(windowHandle, "_d_dwayland_dockstrut", varList); + + } else { + const auto display = QX11Info::display(); + if (!display) { + qWarning() << "QX11Info::display() is " << display; + return; + } + + XcbMisc::instance()->clear_strut_partial(xcb_window_t(mainWindow->winId())); + } + + return; + } + + QRect dockGeometry = getDockGeometry(true); + if (lastRect == dockGeometry + && lastScreenWidth == DIS_INS->screenRawWidth() + && lastScreenHeight == DIS_INS->screenRawHeight()) { + return; + } + + lastRect = dockGeometry; + lastScreenWidth = DIS_INS->screenRawWidth(); + lastScreenHeight = DIS_INS->screenRawHeight(); + qDebug() << "dock real geometry:" << dockGeometry; + qDebug() << "screen width:" << DIS_INS->screenRawWidth() << ", height:" << DIS_INS->screenRawHeight(); + + const qreal &ratio = qApp->devicePixelRatio(); + if (Utils::IS_WAYLAND_DISPLAY) { + QList varList = {0, 0, 0, 0}; + switch (m_position) { + case Position::Top: + varList[0] = 1; + varList[1] = dockGeometry.y() + dockGeometry.height() + WINDOWMARGIN * ratio; + varList[2] = dockGeometry.x(); + varList[3] = dockGeometry.x() + dockGeometry.width(); + break; + case Position::Bottom: + varList[0] = 3; + varList[1] = DIS_INS->screenRawHeight() - dockGeometry.y() + WINDOWMARGIN * ratio; + varList[2] = dockGeometry.x(); + varList[3] = dockGeometry.x() + dockGeometry.width(); + break; + case Position::Left: + varList[0] = 0; + varList[1] = dockGeometry.x() + dockGeometry.width() + WINDOWMARGIN * ratio; + varList[2] = dockGeometry.y(); + varList[3] = dockGeometry.y() + dockGeometry.height(); + break; + case Position::Right: + varList[0] = 2; + varList[1] = DIS_INS->screenRawWidth() - dockGeometry.x() + WINDOWMARGIN * ratio; + varList[2] = dockGeometry.y(); + varList[3] = dockGeometry.y() + dockGeometry.height(); + break; + } + + QPlatformWindow *windowHandle = mainWindow->windowHandle()->handle(); + if (windowHandle) { + QGuiApplication::platformNativeInterface()->setWindowProperty(windowHandle,"_d_dwayland_dockstrut", varList); + } + } else { + XcbMisc::Orientation orientation = XcbMisc::OrientationTop; + double strut = 0; + double strutStart = 0; + double strutEnd = 0; + + switch (m_position) { + case Position::Top: + orientation = XcbMisc::OrientationTop; + strut = dockGeometry.y() + dockGeometry.height(); + strutStart = dockGeometry.x(); + strutEnd = qMin(dockGeometry.x() + dockGeometry.width(), dockGeometry.right()); + break; + case Position::Bottom: + orientation = XcbMisc::OrientationBottom; + strut = DIS_INS->screenRawHeight() - dockGeometry.y(); + strutStart = dockGeometry.x(); + strutEnd = qMin(dockGeometry.x() + dockGeometry.width(), dockGeometry.right()); + break; + case Position::Left: + orientation = XcbMisc::OrientationLeft; + strut = dockGeometry.x() + dockGeometry.width(); + strutStart = dockGeometry.y(); + strutEnd = qMin(dockGeometry.y() + dockGeometry.height(), dockGeometry.bottom()); + break; + case Position::Right: + orientation = XcbMisc::OrientationRight; + strut = DIS_INS->screenRawWidth() - dockGeometry.x(); + strutStart = dockGeometry.y(); + strutEnd = qMin(dockGeometry.y() + dockGeometry.height(), dockGeometry.bottom()); + break; + } + + qDebug() << "set reserved area to xcb:" << strut << strutStart << strutEnd; + + const auto display = QX11Info::display(); + if (!display) { + qWarning() << "QX11Info::display() is " << display; + return; + } + + XcbMisc::instance()->set_strut_partial(static_cast(mainWindow->winId()), orientation, + static_cast(strut + WINDOWMARGIN * ratio), // 设置窗口与屏幕边缘距离,需要乘缩放 + static_cast(strutStart), // 设置任务栏起点坐标(上下为x,左右为y) + static_cast(strutEnd)); // 设置任务栏终点坐标(上下为x,左右为y) + } +} + +void WindowManager::onRequestUpdate() +{ + // 如果当前正在执行动画,则无需设置 + if (m_multiScreenWorker->testState(MultiScreenWorker::ChangePositionAnimationStart) + || m_multiScreenWorker->testState(MultiScreenWorker::ShowAnimationStart) + || m_multiScreenWorker->testState(MultiScreenWorker::HideAnimationStart)) + return; + + QScreen *screen = DIS_INS->screen(DOCKSCREEN_INS->current()); + // 查找发送信号的窗口 + MainWindowBase *dragWindow = qobject_cast(sender()); + if (!dragWindow || !screen) + return; + + QRect dragGeometry = dragWindow->geometry(); + for (MainWindowBase *mainWindow : m_topWindows) { + if (!mainWindow->isVisible()) + continue; + + QRect windowShowSize = mainWindow->getDockGeometry(screen, m_multiScreenWorker->position(), + m_multiScreenWorker->displayMode(), Dock::HideState::Show); + switch(m_position) { + case Dock::Position::Top: { + windowShowSize.setHeight(dragGeometry.height()); + break; + } + case Dock::Position::Bottom: { + int bottomY = windowShowSize.y() + windowShowSize.height(); + windowShowSize.setY(bottomY - dragGeometry.height()); + windowShowSize.setHeight(dragGeometry.height()); + break; + } + case Dock::Position::Left: { + windowShowSize.setWidth(dragGeometry.width()); + break; + } + case Dock::Position::Right: { + int righyX = windowShowSize.x() + windowShowSize.width(); + windowShowSize.setX(righyX - dragGeometry.width()); + windowShowSize.setWidth(dragGeometry.width()); + break; + } + } + + mainWindow->blockSignals(true); + mainWindow->raise(); + mainWindow->setFixedSize(windowShowSize.size()); + mainWindow->move(windowShowSize.topLeft()); + mainWindow->resetPanelGeometry(); + mainWindow->blockSignals(false); + } + + // 抛出geometry变化的信号,通知控制中心调整尺寸 + Q_EMIT panelGeometryChanged(); +} diff --git a/frame/window/windowmanager.h b/frame/window/windowmanager.h new file mode 100644 index 000000000..6b33289d5 --- /dev/null +++ b/frame/window/windowmanager.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 WINDOWMANAGER_H +#define WINDOWMANAGER_H + +#include "constants.h" +#include "statusnotifierwatcher_interface.h" + +#include + +namespace Dtk {namespace Gui { class DWindowManagerHelper; }} + +class MainWindowBase; +class MainWindow; +class TrayMainWindow; +class MultiScreenWorker; +class MenuWorker; +class QDBusConnectionInterface; + +using namespace Dtk::Gui; + +class WindowManager : public QObject +{ + Q_OBJECT + +public: + explicit WindowManager(MultiScreenWorker *multiScreenWorker, QObject *parent = nullptr); + ~WindowManager() override; + + void addWindow(MainWindowBase *window); + void launch(); + void sendNotifications(); + void callShow(); + void resizeDock(int offset, bool dragging); + QRect geometry() const; + +Q_SIGNALS: + void panelGeometryChanged(); + +private: + void initConnection(); + void initSNIHost(); + void initMember(); + void updateMainGeometry(const Dock::HideState &hideState); + QParallelAnimationGroup *createAnimationGroup(const Dock::AniAction &aniAction, const QString &screenName, const Dock::Position &position) const; + + void showAniFinish(); + void hideAniFinish(); + QRect getDockGeometry(bool withoutScale = false) const; // 计算左右侧加起来的区域大小 + + void RegisterDdeSession(); + +private Q_SLOTS: + void onRequestUpdate(); // 调整尺寸的时候 + + void onUpdateDockGeometry(const Dock::HideMode &hideMode); + void onPositionChanged(const Dock::Position &position); + void onDisplayModeChanged(const Dock::DisplayMode &displayMode); + + void onDbusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); + + void onPlayAnimation(const QString &screenName, const Dock::Position &pos, Dock::AniAction act, bool containMouse = false, bool updatePos = false); + void onChangeDockPosition(QString fromScreen, QString toScreen, const Dock::Position &fromPos, const Dock::Position &toPos); + void onRequestUpdateFrontendGeometry(); + void onRequestNotifyWindowManager(); + +private: + MultiScreenWorker *m_multiScreenWorker; + QString m_sniHostService; + + Dock::DisplayMode m_displayMode; + Dock::Position m_position; + + QDBusConnectionInterface *m_dbusDaemonInterface; + org::kde::StatusNotifierWatcher *m_sniWatcher; // DBUS状态通知 + QList m_topWindows; +}; + +#endif // WINDOWMANAGER_H diff --git a/interfaces/constants.h b/interfaces/constants.h index 669699d73..407aaff2b 100644 --- a/interfaces/constants.h +++ b/interfaces/constants.h @@ -43,6 +43,8 @@ namespace Dock { // 插件最小尺寸,图标采用深色 #define PLUGIN_MIN_ICON_NAME "-dark" +// dock最小尺寸 +#define DOCK_MIN_SIZE 40 // dock最大尺寸 #define DOCK_MAX_SIZE 100 /// @@ -96,6 +98,11 @@ enum HideState { Hide = 2, }; +enum class AniAction { + Show = 0, + Hide +}; + #define IS_TOUCH_STATE "isTouchState" }