Skip to content

Commit e48d114

Browse files
committed
fix(touch): enable manual touch scrolling for network plugin in Wayland
Under Wayland, Qt's gesture manager fails to find correct target widgets for touch events inside QTreeView and QScrollArea, leading to unresponsive touch scrolling. Direct interception of Touch events on the viewport, translation into scrollbar value updates, and generation of precise mouse button events for item interaction without drag. Log: Fix touch scrolling for NetView Pms: BUG-351259
1 parent 7bf893c commit e48d114

File tree

2 files changed

+74
-12
lines changed

2 files changed

+74
-12
lines changed

common-plugin/networkdialog/networkpanel.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ void NetworkPanel::initUi()
111111
m_netListView->setMouseTracking(true);
112112
m_netListView->setItemMargins(QMargins(10, 0, 10, 0));
113113
m_netListView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
114+
m_netListView->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
114115
m_netListView->setItemRadius(0);
115116

116117
NetworkDelegate *delegate = new NetworkDelegate(m_netListView);
@@ -163,11 +164,8 @@ void NetworkPanel::initUi()
163164
setControlBackground();
164165

165166
// 支持在触摸屏上滚动
166-
QScroller::grabGesture(m_netListView->viewport(), QScroller::LeftMouseButtonGesture);
167-
QScroller *scroller = QScroller::scroller(m_netListView->window());
168-
QScrollerProperties sp;
169-
sp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
170-
scroller->setScrollerProperties(sp);
167+
m_netListView->setAttribute(Qt::WA_AcceptTouchEvents, true);
168+
m_netListView->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, true);
171169
}
172170

173171
void NetworkPanel::initConnection()

net-view/window/netview.cpp

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <QEvent>
1616
#include <QHoverEvent>
1717
#include <QScrollBar>
18+
#include <QCoreApplication>
1819
#include <QScroller>
1920
#include <QScrollerProperties>
2021
#include <QSortFilterProxyModel>
@@ -66,6 +67,8 @@ NetView::NetView(NetManager *manager)
6667
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
6768
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
6869
setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
70+
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
71+
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
6972

7073
setSelectionMode(QAbstractItemView::NoSelection);
7174
setRootIsDecorated(false);
@@ -83,13 +86,8 @@ NetView::NetView(NetManager *manager)
8386
connect(this, &NetView::activated, this, &NetView::onActivated);
8487

8588
// 支持在触摸屏上滚动
86-
QScroller::grabGesture(viewport(), QScroller::TouchGesture);
87-
QScrollerProperties sp = QScroller::scroller(viewport())->scrollerProperties();
88-
sp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
89-
sp.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
90-
sp.setScrollMetric(QScrollerProperties::DecelerationFactor, 0.5);
91-
sp.setScrollMetric(QScrollerProperties::MaximumVelocity, 0.5);
92-
QScroller::scroller(viewport())->setScrollerProperties(sp);
89+
setAttribute(Qt::WA_AcceptTouchEvents, true);
90+
viewport()->setAttribute(Qt::WA_AcceptTouchEvents, true);
9391
}
9492

9593
NetView::~NetView() = default;
@@ -183,6 +181,72 @@ void NetView::rowsInserted(const QModelIndex &parent, int start, int end)
183181

184182
bool NetView::viewportEvent(QEvent *event)
185183
{
184+
static QPointF s_touchPressPos;
185+
static bool s_isDrag = false;
186+
187+
const QEvent::Type type = event->type();
188+
if (type == QEvent::TouchBegin || type == QEvent::TouchUpdate ||
189+
type == QEvent::TouchEnd || type == QEvent::TouchCancel) {
190+
191+
QTouchEvent *te = static_cast<QTouchEvent *>(event);
192+
if (te->points().isEmpty()) {
193+
event->accept();
194+
return true;
195+
}
196+
197+
QEventPoint pt = te->points().first();
198+
199+
switch (type) {
200+
case QEvent::TouchBegin: {
201+
s_touchPressPos = pt.globalPosition();
202+
s_isDrag = false;
203+
break;
204+
}
205+
case QEvent::TouchUpdate: {
206+
qreal deltaY = pt.globalPosition().y() - s_touchPressPos.y();
207+
qreal deltaX = pt.globalPosition().x() - s_touchPressPos.x();
208+
209+
if (!s_isDrag && (qAbs(deltaY) >= QApplication::startDragDistance() || qAbs(deltaX) >= QApplication::startDragDistance())) {
210+
s_isDrag = true;
211+
}
212+
213+
if (s_isDrag) {
214+
if (qAbs(deltaY) > 0 && verticalScrollBar()) {
215+
verticalScrollBar()->setValue(verticalScrollBar()->value() - deltaY);
216+
}
217+
if (qAbs(deltaX) > 0 && horizontalScrollBar()) {
218+
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - deltaX);
219+
}
220+
s_touchPressPos = pt.globalPosition();
221+
}
222+
break;
223+
}
224+
case QEvent::TouchEnd: {
225+
if (!s_isDrag) {
226+
// Determine the correct target widget for the click
227+
QWidget *target = viewport();
228+
QPoint widgetPos = pt.position().toPoint();
229+
230+
if (QWidget *child = target->childAt(widgetPos)) {
231+
target = child;
232+
widgetPos = target->mapFrom(viewport(), widgetPos);
233+
}
234+
235+
QMouseEvent press(QEvent::MouseButtonPress, widgetPos, pt.globalPosition(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
236+
QCoreApplication::sendEvent(target, &press);
237+
QMouseEvent release(QEvent::MouseButtonRelease, widgetPos, pt.globalPosition(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
238+
QCoreApplication::sendEvent(target, &release);
239+
}
240+
break;
241+
}
242+
default:
243+
break;
244+
}
245+
246+
event->accept();
247+
return true;
248+
}
249+
186250
switch (event->type()) {
187251
case QEvent::HoverLeave: {
188252
setCurrentIndex(QModelIndex());

0 commit comments

Comments
 (0)