fix: context menu invoke in touch screen

https://github.com/linuxdeepin/internal-discussion/issues/619

Change-Id: I21febec29c06eef80114f9082e6cc02d7468c2d3
This commit is contained in:
listenerri 2018-12-13 11:43:48 +08:00
parent 635d41525f
commit 77570b609a
Notes: gerrit 2018-12-14 15:18:10 +08:00
Verified+1: <jenkins@deepin.com>
Code-Review+2: listenerri <listenerri@gmail.com>
Submitted-by: listenerri <listenerri@gmail.com>
Submitted-at: Fri, 14 Dec 2018 15:18:09 +0800
Reviewed-on: https://cr.deepin.io/40530
Project: dde/dde-dock
Branch: refs/heads/master
6 changed files with 111 additions and 24 deletions

View File

@ -26,8 +26,13 @@
#include <QDebug>
AbstractTrayWidget::AbstractTrayWidget(QWidget *parent, Qt::WindowFlags f)
: QWidget(parent, f)
: QWidget(parent, f),
m_handleMouseReleaseTimer(new QTimer(this))
{
m_handleMouseReleaseTimer->setSingleShot(true);
m_handleMouseReleaseTimer->setInterval(100);
connect(m_handleMouseReleaseTimer, &QTimer::timeout, this, &AbstractTrayWidget::handleMouseRelease);
}
AbstractTrayWidget::~AbstractTrayWidget()
@ -39,7 +44,7 @@ void AbstractTrayWidget::mousePressEvent(QMouseEvent *event)
{
// do not call Parent::mousePressEvent or the DockItem will catch this event
// and show dock-context-menu immediately when right button of mouse is pressed in fashion mode
if (event->buttons() == Qt::RightButton) {
if (event->button() == Qt::RightButton) {
event->accept();
return;
}
@ -49,16 +54,34 @@ void AbstractTrayWidget::mousePressEvent(QMouseEvent *event)
void AbstractTrayWidget::mouseReleaseEvent(QMouseEvent *e)
{
const QPoint point(e->pos() - rect().center());
if (point.manhattanLength() > 24)
//e->accept();
// 由于 XWindowTrayWidget 中对 发送鼠标事件到X窗口的函数, 如 sendClick/sendHoverEvent 中
// 使用了 setX11PassMouseEvent, 而每次调用 setX11PassMouseEvent 时都会导致产生 mousePress 和 mouseRelease 事件
// 因此如果直接在这里处理事件会导致一些问题, 所以使用 Timer 来延迟处理 100 毫秒内的最后一个事件
m_lastMouseReleaseData.first = e->pos();
m_lastMouseReleaseData.second = e->button();
m_handleMouseReleaseTimer->start();
}
void AbstractTrayWidget::handleMouseRelease() {
Q_ASSERT(sender() == m_handleMouseReleaseTimer);
// do not dealwith all mouse event of SystemTray, class SystemTrayItem will handle it
if (trayTyep() == SystemTray)
return;
e->accept();
const QPoint point(m_lastMouseReleaseData.first - rect().center());
if (point.manhattanLength() > 24)
return;
QPoint globalPos = QCursor::pos();
uint8_t buttonIndex = XCB_BUTTON_INDEX_1;
switch (e->button()) {
switch (m_lastMouseReleaseData.second) {
case Qt:: MiddleButton:
buttonIndex = XCB_BUTTON_INDEX_2;
break;

View File

@ -22,6 +22,8 @@
#pragma once
#include <QWidget>
#include <QTimer>
#include <QPair>
class QDBusMessage;
class AbstractTrayWidget: public QWidget
@ -52,5 +54,12 @@ Q_SIGNALS:
protected:
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
void handleMouseRelease();
private:
QTimer *m_handleMouseReleaseTimer;
QPair<QPoint, Qt::MouseButton> m_lastMouseReleaseData;
};

View File

@ -33,6 +33,7 @@ QPointer<DockPopupWindow> SystemTrayItem::PopupWindow = nullptr;
SystemTrayItem::SystemTrayItem(PluginsItemInterface * const pluginInter, const QString &itemKey, QWidget *parent)
: AbstractTrayWidget(parent),
m_popupShown(false),
m_tapAndHold(false),
m_pluginInter(pluginInter),
m_menuManagerInter(new DBusMenuManager(this)),
m_centralWidget(m_pluginInter->itemWidget(itemKey)),
@ -75,6 +76,8 @@ SystemTrayItem::SystemTrayItem(PluginsItemInterface * const pluginInter, const Q
connect(m_popupTipsDelayTimer, &QTimer::timeout, this, &SystemTrayItem::showHoverTips);
connect(m_popupAdjustDelayTimer, &QTimer::timeout, this, &SystemTrayItem::updatePopupPosition, Qt::QueuedConnection);
grabGesture(Qt::TapAndHoldGesture);
}
SystemTrayItem::~SystemTrayItem()
@ -100,22 +103,12 @@ const QImage SystemTrayItem::trayImage()
void SystemTrayItem::sendClick(uint8_t mouseButton, int x, int y)
{
switch (mouseButton) {
case XCB_BUTTON_INDEX_1: {
showPopupApplet(trayPopupApplet());
QProcess::startDetached(trayClickCommand());
break;
}
case XCB_BUTTON_INDEX_2:
break;
case XCB_BUTTON_INDEX_3: {
showContextMenu();
break;
}
default:
qDebug() << "unknown mouse button key";
break;
}
Q_UNUSED(mouseButton);
Q_UNUSED(x);
Q_UNUSED(y);
// do not process this callback
// handle all mouse event in override mouse function
}
QWidget *SystemTrayItem::trayTipsWidget()
@ -169,6 +162,9 @@ bool SystemTrayItem::event(QEvent *event)
}
}
if (event->type() == QEvent::Gesture)
gestureEvent(static_cast<QGestureEvent*>(event));
return AbstractTrayWidget::event(event);
}
@ -201,6 +197,28 @@ void SystemTrayItem::mousePressEvent(QMouseEvent *event)
AbstractTrayWidget::mousePressEvent(event);
}
void SystemTrayItem::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() != Qt::LeftButton) {
return;
}
if (checkAndResetTapHoldGestureState()&& event->source() == Qt::MouseEventSynthesizedByQt) {
qDebug() << "SystemTray: tap and hold gesture detected, ignore the synthesized mouse release event";
return;
}
event->accept();
showPopupApplet(trayPopupApplet());
if (!trayClickCommand().isEmpty()) {
QProcess::startDetached(trayClickCommand());
}
AbstractTrayWidget::mouseReleaseEvent(event);
}
const QPoint SystemTrayItem::popupMarkPoint() const
{
QPoint p(topleftPoint());
@ -330,6 +348,31 @@ void SystemTrayItem::showHoverTips()
showPopupWindow(content);
}
/*!
* \sa DockItem::checkAndResetTapHoldGestureState
*/
bool SystemTrayItem::checkAndResetTapHoldGestureState()
{
bool ret = m_tapAndHold;
m_tapAndHold = false;
return ret;
}
void SystemTrayItem::gestureEvent(QGestureEvent *event)
{
if (!event)
return;
QGesture *gesture = event->gesture(Qt::TapAndHoldGesture);
if (!gesture)
return;
qDebug() << "SystemTray: got TapAndHoldGesture";
m_tapAndHold = true;
}
void SystemTrayItem::showContextMenu()
{
const QString menuJson = contextMenu();

View File

@ -28,6 +28,8 @@
#include "dbus/dbusmenumanager.h"
#include "pluginsiteminterface.h"
#include <QGestureEvent>
class SystemTrayItem : public AbstractTrayWidget
{
Q_OBJECT
@ -53,12 +55,14 @@ public:
QWidget *centralWidget() const;
void detachPluginWidget();
void showContextMenu();
protected:
bool event(QEvent *event) Q_DECL_OVERRIDE;
void enterEvent(QEvent *event) Q_DECL_OVERRIDE;
void leaveEvent(QEvent *event) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
protected:
const QPoint popupMarkPoint() const;
@ -72,8 +76,10 @@ protected:
virtual void showPopupWindow(QWidget * const content, const bool model = false);
virtual void showHoverTips();
bool checkAndResetTapHoldGestureState();
virtual void gestureEvent(QGestureEvent *event);
protected Q_SLOTS:
void showContextMenu();
void onContextMenuAccepted();
private:
@ -81,6 +87,7 @@ private:
private:
bool m_popupShown;
bool m_tapAndHold;
PluginsItemInterface* m_pluginInter;
DBusMenuManager *m_menuManagerInter;

View File

@ -88,7 +88,7 @@ void SystemTraysController::requestContextMenu(PluginsItemInterface * const item
SystemTrayItem *item = pluginItemAt(itemInter, itemKey);
Q_ASSERT(item);
// item->showContextMenu();
item->showContextMenu();
}
void SystemTraysController::requestWindowAutoHide(PluginsItemInterface * const itemInter, const QString &itemKey, const bool autoHide)

View File

@ -132,6 +132,11 @@ void XWindowTrayWidget::mouseMoveEvent(QMouseEvent *e)
{
AbstractTrayWidget::mouseMoveEvent(e);
// ignore the touchEvent
if (e->source() == Qt::MouseEventSynthesizedByQt) {
return;
}
m_sendHoverEvent->start();
}