From 04762453fa1b27e0e1497833bb2b15c89a6cc236 Mon Sep 17 00:00:00 2001 From: songwentao Date: Thu, 21 Oct 2021 16:41:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BB=BB=E5=8A=A1=E6=A0=8F=E6=8B=96?= =?UTF-8?q?=E6=8B=BD=E5=9B=BE=E6=A0=87=E4=BA=A4=E4=BA=92=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 单指长按应用图标超过1s后显示右键菜单,继续拖拽应用进行调整位置,拖拽的过程中右键菜单隐藏 Log: 优化任务栏拖拽图标人机交互逻辑 Influence: 优化任务栏拖拽图标与右键菜单显示的人机交互逻辑 Task: https://pms.uniontech.com/zentao/task-view-86283.html Change-Id: I15b4e0cafeb94fc4545090e60965d217b93ab8cd --- frame/item/dockitem.cpp | 9 +- frame/item/dockitem.h | 3 +- frame/util/menudialog.cpp | 97 ++++++++++++++++++++ frame/util/menudialog.h | 56 +++++++++++ plugins/keyboard-layout/dbusadaptors.cpp | 4 +- plugins/keyboard-layout/dbusadaptors.h | 4 +- plugins/tray/snitraywidget.cpp | 82 ++++++++++++++--- plugins/tray/snitraywidget.h | 11 ++- plugins/tray/system-trays/systemtrayitem.cpp | 47 +++++++++- plugins/tray/system-trays/systemtrayitem.h | 3 +- plugins/tray/xembedtraywidget.cpp | 15 +++ plugins/tray/xembedtraywidget.h | 1 + 12 files changed, 303 insertions(+), 29 deletions(-) create mode 100644 frame/util/menudialog.cpp create mode 100644 frame/util/menudialog.h diff --git a/frame/item/dockitem.cpp b/frame/item/dockitem.cpp index 740c1944b..a64235072 100644 --- a/frame/item/dockitem.cpp +++ b/frame/item/dockitem.cpp @@ -42,6 +42,7 @@ DockItem::DockItem(QWidget *parent) , m_draging(false) , m_popupTipsDelayTimer(new QTimer(this)) , m_popupAdjustDelayTimer(new QTimer(this)) + , m_contextMenu(new Menu(this, this)) { if (PopupWindow.isNull()) { DockPopupWindow *arrowRectangle = new DockPopupWindow(nullptr); @@ -64,7 +65,7 @@ DockItem::DockItem(QWidget *parent) connect(m_popupTipsDelayTimer, &QTimer::timeout, this, &DockItem::showHoverTips); connect(m_popupAdjustDelayTimer, &QTimer::timeout, this, &DockItem::updatePopupPosition, Qt::QueuedConnection); - connect(&m_contextMenu, &QMenu::triggered, this, &DockItem::menuActionClicked); + connect(m_contextMenu, &Menu::triggered, this, &DockItem::menuActionClicked); grabGesture(Qt::TapAndHoldGesture); @@ -233,7 +234,7 @@ void DockItem::showContextMenu() QJsonObject jsonMenu = jsonDocument.object(); - qDeleteAll(m_contextMenu.actions()); + qDeleteAll(m_contextMenu->actions()); QJsonArray jsonMenuItems = jsonMenu.value("items").toArray(); for (auto item : jsonMenuItems) { @@ -243,13 +244,13 @@ void DockItem::showContextMenu() action->setChecked(itemObj.value("checked").toBool()); action->setData(itemObj.value("itemId").toString()); action->setEnabled(itemObj.value("isActive").toBool()); - m_contextMenu.addAction(action); + m_contextMenu->addAction(action); } hidePopup(); emit requestWindowAutoHide(false); - m_contextMenu.popup(QCursor::pos()); + m_contextMenu->popup(QCursor::pos()); onContextMenuAccepted(); } diff --git a/frame/item/dockitem.h b/frame/item/dockitem.h index 31ac5cd88..9e7341b7b 100644 --- a/frame/item/dockitem.h +++ b/frame/item/dockitem.h @@ -24,6 +24,7 @@ #include "constants.h" #include "dockpopupwindow.h" +#include "menudialog.h" #include #include @@ -110,12 +111,12 @@ protected: bool m_popupShown; bool m_tapAndHold; bool m_draging; - QMenu m_contextMenu; QPointer m_lastPopupWidget; QTimer *m_popupTipsDelayTimer; QTimer *m_popupAdjustDelayTimer; + Menu *m_contextMenu; static Position DockPosition; static DisplayMode DockDisplayMode; diff --git a/frame/util/menudialog.cpp b/frame/util/menudialog.cpp new file mode 100644 index 000000000..47659209c --- /dev/null +++ b/frame/util/menudialog.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2020 ~ 2021 Deepin Technology Co., Ltd. + * + * Author: songwentao + * + * Maintainer: songwentao + * + * 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 . + * + * This program aims to cache the the icon and name of apps to the hash table, + * which can decrease the repeated resource consumption of loading the app info in the + * running time. + */ + +#include "menudialog.h" + +#include +#include +#include + +Menu::Menu(QWidget *dockItem, QWidget *parent) + : QMenu(parent) + , m_dockItem(dockItem) + , m_eventInter(new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus(), this)) + , m_dockInter(new DBusDock("com.deepin.dde.daemon.Dock", "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this)) +{ + setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::Dialog); + setObjectName("rightMenu"); + qApp->installEventFilter(this); + m_dockItem->installEventFilter(this); + + // 点击任务栏以外区域时,关闭右键菜单 + connect(m_eventInter, &XEventMonitor::ButtonPress, this, &Menu::onButtonPress); +} + +void Menu::onButtonPress() +{ + if (!QRect(m_dockInter->frontendWindowRect()).contains(QCursor::pos())) + this->hide(); +} + +/** 右键菜单显示后在很多场景下都需要隐藏,为避免在各个控件中分别做隐藏右键菜单窗口的处理, + * 因此这里统一做了处理。 + * @brief Menu::eventFilter + * @param watched 过滤器监听对象 + * @param event 过滤器事件对象 + * @return 返回true, 事件不再向下传递,返回false,事件向下传递 + */ +bool Menu::eventFilter(QObject *watched, QEvent *event) +{ + // 存在rightMenu和rightMenuWindow的对象名 + if (!watched->objectName().startsWith("rightMenu")) { + if (event->type() == QEvent::MouseButtonPress) { + if (watched != m_dockItem && watched != this && this->isVisible()) { + // 鼠标点击时,除当前菜单外,其他显示的菜单都要隐藏 + hide(); + } + } else if (event->type() == QEvent::DragMove || event->type() == QEvent::Wheel || event->type() == QEvent::Move) { + // 按下应用拖动,按下应用从菜单上方移动时,鼠标滚轮滚动时,隐藏右键菜单 + hide(); + } + + // 当右键菜单显示时捕获鼠标的release事件,click=press+release, + // 让click无效,从而让启动器窗口不关闭 + if (event->type() == QEvent::MouseButtonRelease) { + QMouseEvent *mouseEvent = static_cast(event); + if (mouseEvent->source() == Qt::MouseEventSynthesizedByQt) { + if (isVisible()) + return true; + } + } + + // 处理当右键菜单显示时,esc按下,关闭右键菜单,保持和模态框一样的效果 + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Escape) { + if (isVisible()) { + hide(); + return true; + } + } + } + } + + return QMenu::eventFilter(watched, event); +} diff --git a/frame/util/menudialog.h b/frame/util/menudialog.h new file mode 100644 index 000000000..d18ae602a --- /dev/null +++ b/frame/util/menudialog.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2020 ~ 2021 Deepin Technology Co., Ltd. + * + * Author: songwentao + * + * Maintainer: songwentao + * + * 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 . + * + * This program aims to cache the the icon and name of apps to the hash table, + * which can decrease the repeated resource consumption of loading the app info in the + * running time. + */ + +#ifndef MYMENU_H +#define MYMENU_H + +#include +#include + +#include +#include + +using DBusDock = com::deepin::dde::daemon::Dock; +using XEventMonitor = ::com::deepin::api::XEventMonitor; + +class Menu : public QMenu +{ + Q_OBJECT + +public: + explicit Menu(QWidget *dockItem = nullptr, QWidget *parent = nullptr); + + void onButtonPress(); + +protected: + bool eventFilter(QObject *watched, QEvent *event); + +private: + QWidget *m_dockItem; + XEventMonitor *m_eventInter; + DBusDock *m_dockInter; +}; + +#endif //MYMENU_H diff --git a/plugins/keyboard-layout/dbusadaptors.cpp b/plugins/keyboard-layout/dbusadaptors.cpp index 250e794bd..50b361d4e 100644 --- a/plugins/keyboard-layout/dbusadaptors.cpp +++ b/plugins/keyboard-layout/dbusadaptors.cpp @@ -28,7 +28,7 @@ DBusAdaptors::DBusAdaptors(QObject *parent) m_keyboard(new Keyboard("com.deepin.daemon.InputDevices", "/com/deepin/daemon/InputDevice/Keyboard", QDBusConnection::sessionBus(), this)), - m_menu(new QMenu()), + m_menu(new Menu()), m_gsettings(Utils::ModuleSettingsPtr("keyboard", QByteArray(), this)) { m_keyboard->setSync(false); @@ -36,7 +36,7 @@ DBusAdaptors::DBusAdaptors(QObject *parent) connect(m_keyboard, &Keyboard::CurrentLayoutChanged, this, &DBusAdaptors::onCurrentLayoutChanged); connect(m_keyboard, &Keyboard::UserLayoutListChanged, this, &DBusAdaptors::onUserLayoutListChanged); - connect(m_menu, &QMenu::triggered, this, &DBusAdaptors::handleActionTriggered); + connect(m_menu, &Menu::triggered, this, &DBusAdaptors::handleActionTriggered); // init data initAllLayoutList(); diff --git a/plugins/keyboard-layout/dbusadaptors.h b/plugins/keyboard-layout/dbusadaptors.h index 355165153..1b7e728c2 100644 --- a/plugins/keyboard-layout/dbusadaptors.h +++ b/plugins/keyboard-layout/dbusadaptors.h @@ -20,6 +20,8 @@ #ifndef DBUSADAPTORS_H #define DBUSADAPTORS_H +#include "menudialog.h" + #include #include #include @@ -73,7 +75,7 @@ private: private: Keyboard *m_keyboard; - QMenu *m_menu; + Menu *m_menu; QAction *m_addLayoutAction; QString m_currentLayoutRaw; diff --git a/plugins/tray/snitraywidget.cpp b/plugins/tray/snitraywidget.cpp index 6b6c3b26c..3d9d58582 100644 --- a/plugins/tray/snitraywidget.cpp +++ b/plugins/tray/snitraywidget.cpp @@ -39,10 +39,10 @@ QPointer SNITrayWidget::PopupWindow = nullptr; Dock::Position SNITrayWidget::DockPosition = Dock::Position::Top; using namespace Dock; SNITrayWidget::SNITrayWidget(const QString &sniServicePath, QWidget *parent) - : AbstractTrayWidget(parent), - m_dbusMenuImporter(nullptr), - m_menu(nullptr), - m_updateIconTimer(new QTimer(this)) + : AbstractTrayWidget(parent) + , m_dbusMenuImporter(nullptr) + , m_menu(nullptr) + , m_updateIconTimer(new QTimer(this)) , m_updateOverlayIconTimer(new QTimer(this)) , m_updateAttentionIconTimer(new QTimer(this)) , m_sniServicePath(sniServicePath) @@ -181,6 +181,7 @@ void SNITrayWidget::sendClick(uint8_t mouseButton, int x, int y) if (LeftClickInvalidIdList.contains(m_sniId)) { showContextMenu(x, y); } else { + // 输入法切换等功能入口 m_sniInter->Activate(x, y); } break; @@ -191,7 +192,6 @@ void SNITrayWidget::sendClick(uint8_t mouseButton, int x, int y) showContextMenu(x, y); break; default: - qDebug() << "unknown mouse button key"; break; } } @@ -272,15 +272,13 @@ void SNITrayWidget::initMenu() return; } - qDebug() << "using sni service path:" << m_dbusService << "menu path:" << sniMenuPath; - m_dbusMenuImporter = new DBusMenuImporter(m_dbusService, sniMenuPath, ASYNCHRONOUS, this); - qDebug() << "generate the sni menu object"; - + // 创建sni协议插件的右键菜单 m_menu = m_dbusMenuImporter->menu(); - - qDebug() << "the sni menu obect is:" << m_menu; + m_menu->setObjectName("sniMenu"); + m_menu->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::Dialog); + qApp->installEventFilter(this); } void SNITrayWidget::refreshIcon() @@ -337,7 +335,7 @@ void SNITrayWidget::showContextMenu(int x, int y) // 这里的PopupWindow属性是置顶的,如果不隐藏,会导致菜单显示不出来 hidePopup(); - // ContextMenu does not work + // 第三方的右键菜单,事件过滤方式无法捕获,修改x,y值不能改变菜单弹出位置 if (m_sniMenuPath.path().startsWith("/NO_DBUSMENU")) { m_sniInter->ContextMenu(x, y); } else { @@ -732,6 +730,66 @@ const QPoint SNITrayWidget::popupMarkPoint() const return p; } +bool SNITrayWidget::eventFilter(QObject *watched, QEvent *event) +{ + if (!m_menu) + return QWidget::eventFilter(watched, event); + + QPoint startPos = QPoint(); + if (!watched->objectName().startsWith("sniMenu")) { + if (event->type() == QEvent::MouseButtonPress) { + QMouseEvent *mouseEvent = static_cast(event); + if (mouseEvent->button() == Qt::LeftButton) { + if (m_sniMenuPath.path().startsWith("/NO_DBUSMENU")) { + // 关闭中文输入法或者五笔输入法,当前的关闭方式无效 + QMouseEvent *pressEvent = new QMouseEvent(QEvent::MouseButtonPress, mapToGlobal(this->pos()), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + qApp->postEvent(this->parentWidget(), pressEvent); + } else { + m_menu->hide(); + } + } + startPos = mouseEvent->pos(); + } else if (event->type() == QEvent::DragMove || event->type() == QEvent::Move) { + if (m_sniMenuPath.path().startsWith("/NO_DBUSMENU")) { + // 关闭中文输入法或者五笔输入法,当前的关闭方式无效 + QMouseEvent *pressEvent = new QMouseEvent(QEvent::MouseButtonPress, mapToGlobal(this->pos()), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + qApp->postEvent(this->parentWidget(), pressEvent); + } else { + m_menu->hide(); + } + } + + // 让click无效,避免点击到插件上 + if (event->type() == QEvent::MouseButtonRelease) { + QMouseEvent *mouseEvent = static_cast(event); + if (mouseEvent->source() == Qt::MouseEventSynthesizedByQt) { + if (isVisible()) + return true; + } + } + + // 处理当右键菜单显示时,esc按下,关闭右键菜单,保持和模态框一样的效果 + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Escape) { + if (!isVisible()) + return false; + + if (m_sniMenuPath.path().startsWith("/NO_DBUSMENU")) { + // 关闭中文输入法或者五笔输入法,当前的关闭方式无效 + QMouseEvent *pressEvent = new QMouseEvent(QEvent::MouseButtonPress, mapToGlobal(this->pos()), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + qApp->postEvent(this->parentWidget(), pressEvent); + } else { + m_menu->hide(); + } + return true; + } + } + } + + return QWidget::eventFilter(watched, event); +} + void SNITrayWidget::showPopupWindow(QWidget *const content, const bool model) { m_popupShown = true; diff --git a/plugins/tray/snitraywidget.h b/plugins/tray/snitraywidget.h index 9ecb016a5..6fa568b50 100644 --- a/plugins/tray/snitraywidget.h +++ b/plugins/tray/snitraywidget.h @@ -74,6 +74,13 @@ public: static void setDockPostion(const Dock::Position pos) { DockPosition = pos; } +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + void enterEvent(QEvent *event) override; + void leaveEvent(QEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *e) override; + Q_SIGNALS: void statusChanged(SNITrayWidget::ItemStatus status); @@ -100,10 +107,6 @@ private Q_SLOTS: void hidePopup(); void hideNonModel(); void popupWindowAccept(); - void enterEvent(QEvent *event) override; - void leaveEvent(QEvent *event) override; - void mousePressEvent(QMouseEvent *event) override; - void mouseReleaseEvent(QMouseEvent *e) override; private: void paintEvent(QPaintEvent *e) override; diff --git a/plugins/tray/system-trays/systemtrayitem.cpp b/plugins/tray/system-trays/systemtrayitem.cpp index cfb144187..8e9809802 100644 --- a/plugins/tray/system-trays/systemtrayitem.cpp +++ b/plugins/tray/system-trays/systemtrayitem.cpp @@ -24,6 +24,7 @@ #include #include +#include #include @@ -34,6 +35,7 @@ SystemTrayItem::SystemTrayItem(PluginsItemInterface *const pluginInter, const QS : AbstractTrayWidget(parent) , m_popupShown(false) , m_tapAndHold(false) + , m_contextMenu(new QMenu) , m_pluginInter(pluginInter) , m_centralWidget(m_pluginInter->itemWidget(itemKey)) , m_popupTipsDelayTimer(new QTimer(this)) @@ -82,18 +84,24 @@ SystemTrayItem::SystemTrayItem(PluginsItemInterface *const pluginInter, const QS connect(m_popupTipsDelayTimer, &QTimer::timeout, this, &SystemTrayItem::showHoverTips); connect(m_popupAdjustDelayTimer, &QTimer::timeout, this, &SystemTrayItem::updatePopupPosition, Qt::QueuedConnection); - connect(&m_contextMenu, &QMenu::triggered, this, &SystemTrayItem::menuActionClicked); + connect(m_contextMenu, &QMenu::triggered, this, &SystemTrayItem::menuActionClicked); if (m_gsettings) connect(m_gsettings, &QGSettings::changed, this, &SystemTrayItem::onGSettingsChanged); grabGesture(Qt::TapAndHoldGesture); + + m_contextMenu->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::Dialog); + m_contextMenu->setObjectName("trayMenu"); + qApp->installEventFilter(m_contextMenu); } SystemTrayItem::~SystemTrayItem() { if (m_popupShown) popupWindowAccept(); + + delete m_contextMenu; } QString SystemTrayItem::itemKeyForConfig() @@ -261,6 +269,37 @@ void SystemTrayItem::showEvent(QShowEvent *event) return AbstractTrayWidget::showEvent(event); } +bool SystemTrayItem::eventFilter(QObject *watched, QEvent *event) +{ + if (!watched->objectName().startsWith("trayMenu")) { + if (event->type() == QEvent::MouseButtonPress) { + QMouseEvent *mouseEvent = static_cast(event); + if (mouseEvent->button() == Qt::LeftButton) + m_contextMenu->hide(); + } else if (event->type() == QEvent::DragMove || event->type() == QEvent::Move || event->type() == QEvent::Leave) { + m_contextMenu->hide(); + } + + // 让click无效,避免点击到插件上 + if (event->type() == QEvent::MouseButtonRelease) { + QMouseEvent *mouseEvent = static_cast(event); + if (mouseEvent->source() == Qt::MouseEventSynthesizedByQt && isVisible()) + return true; + } + + // 处理当右键菜单显示时,esc按下,关闭右键菜单,保持和模态框一样的效果 + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Escape && isVisible()) { + m_contextMenu->hide(); + return true; + } + } + } + + return QWidget::eventFilter(watched, event); +} + const QPoint SystemTrayItem::popupMarkPoint() const { QPoint p(topleftPoint()); @@ -427,7 +466,7 @@ void SystemTrayItem::showContextMenu() QJsonObject jsonMenu = jsonDocument.object(); - qDeleteAll(m_contextMenu.actions()); + qDeleteAll(m_contextMenu->actions()); QJsonArray jsonMenuItems = jsonMenu.value("items").toArray(); for (auto item : jsonMenuItems) { @@ -437,13 +476,13 @@ void SystemTrayItem::showContextMenu() action->setChecked(itemObj.value("checked").toBool()); action->setData(itemObj.value("itemId").toString()); action->setEnabled(itemObj.value("isActive").toBool()); - m_contextMenu.addAction(action); + m_contextMenu->addAction(action); } hidePopup(); emit requestWindowAutoHide(false); - m_contextMenu.exec(QCursor::pos()); + m_contextMenu->popup(QCursor::pos()); onContextMenuAccepted(); } diff --git a/plugins/tray/system-trays/systemtrayitem.h b/plugins/tray/system-trays/systemtrayitem.h index e37c84a89..fdc0b1549 100644 --- a/plugins/tray/system-trays/systemtrayitem.h +++ b/plugins/tray/system-trays/systemtrayitem.h @@ -70,6 +70,7 @@ protected: void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void showEvent(QShowEvent* event) override; + bool eventFilter(QObject *watched, QEvent *event) override; protected: const QPoint popupMarkPoint() const; @@ -96,7 +97,7 @@ private: private: bool m_popupShown; bool m_tapAndHold; - QMenu m_contextMenu; + QMenu *m_contextMenu; PluginsItemInterface* m_pluginInter; QWidget *m_centralWidget; diff --git a/plugins/tray/xembedtraywidget.cpp b/plugins/tray/xembedtraywidget.cpp index aeced6f42..62e123a0b 100644 --- a/plugins/tray/xembedtraywidget.cpp +++ b/plugins/tray/xembedtraywidget.cpp @@ -134,12 +134,27 @@ void XEmbedTrayWidget::paintEvent(QPaintEvent *e) painter.end(); } +void XEmbedTrayWidget::mousePressEvent(QMouseEvent *e) +{ + // 支持触摸屏触摸按下,显示右键菜单 + if (e->source() == Qt::MouseEventSynthesizedByQt) { + QTimer::singleShot(100, this, [ & ] { + // 右键 + sendClick(XCB_BUTTON_INDEX_3, QCursor::pos().x(), QCursor::pos().y()); + }); + return; + } +} + void XEmbedTrayWidget::mouseMoveEvent(QMouseEvent *e) { AbstractTrayWidget::mouseMoveEvent(e); // ignore the touchEvent if (e->source() == Qt::MouseEventSynthesizedByQt) { + // 临时方案隐藏微信等应用的右键菜单 + // 左键 + sendClick(XCB_BUTTON_INDEX_2, QCursor::pos().x(), QCursor::pos().y()); return; } diff --git a/plugins/tray/xembedtraywidget.h b/plugins/tray/xembedtraywidget.h index 7813275bf..df0d3dc4e 100644 --- a/plugins/tray/xembedtraywidget.h +++ b/plugins/tray/xembedtraywidget.h @@ -47,6 +47,7 @@ public: private: void showEvent(QShowEvent *e) override; void paintEvent(QPaintEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; void configContainerPosition();