status-im / status-desktop

Status Desktop client made in Nim & QML
https://status.app
Mozilla Public License 2.0
286 stars 78 forks source link

dApp - sd-6 - Cannot scroll connected dApps list using mouse #15595

Closed glitchminer closed 4 weeks ago

glitchminer commented 1 month ago

Bug Report

Description

Could not scroll dApp last using scroll wheel and no scroll bar appeared when connected dApp list is long

image

Steps to reproduce

Populate connected dApps list Attempt to scroll using mouse

Expected behavior

List is scrollable

Additional Information

clauxx commented 1 month ago

can it be scrolled otherwise, like by dragging?

glitchminer commented 1 month ago

can it be scrolled otherwise, like by dragging?

Yes, it can be dragged. It's possibly related to other scroll wheel issues such as https://github.com/status-im/status-desktop/issues/3589

clauxx commented 1 month ago

@Seitseman can you have a look at this?

Seitseman commented 1 month ago

This issue is not reproducible on win11, trying on Mac

caybro commented 1 month ago

This issue is not reproducible on win11, trying on Mac

Yeah, typically you will see different behavior across different OSs because Qt itself uses a different input (mouse/wheel/touch) drivers to get the data from

caybro commented 1 month ago

And second, a "scroll" is really a different thing (codepath) when done using a mouse wheel or a touch/pad gesture

Seitseman commented 1 month ago

Checking Qt source code it looks like TouchPad and Mouse Wheel both generate QMouseWheel events, but with different values for acceleration, angle/pixel data. I've added env variable QT_LOGGING_RULES=qt.quick.handler.wheel*=true;qt.quick.wheel.*=true And ran storybook/status app and here are some findings: for mouse wheel I see the following "bad" output, when no actuall list scrolling occurs:

qt.quick.wheel.target: QWheelEvent(Qt::NoScrollPhase, pixelDelta=QPoint(0,-84), angleDelta=QPoint(0,-168)) -> StatusListView_QMLTYPE_267(0x600000ed7e90, parent=0x600000ed7d30, geometry=8,0 296x290)
qt.quick.wheel.target: QWheelEvent(Qt::NoScrollPhase, pixelDelta=QPoint(0,-85), angleDelta=QPoint(0,-170)) -> StatusListView_QMLTYPE_267(0x600000ed7e90, parent=0x600000ed7d30, geometry=8,0 296x290)
...

Whereas, with two finger gesture scrolling on touchpad I get:

qt.quick.wheel.target: QWheelEvent(Qt::ScrollBegin, pixelDelta=QPoint(0,-1), angleDelta=QPoint(0,-2)) -> StatusListView_QMLTYPE_267(0x600000ed7e90, parent=0x600000ed7d30, geometry=8,0 296x290)
qt.quick.wheel.target: QWheelEvent(Qt::ScrollUpdate, pixelDelta=QPoint(0,-3), angleDelta=QPoint(0,-6)) -> StatusListView_QMLTYPE_267(0x600000ed7e90, parent=0x600000ed7d30, geometry=8,0 296x290)
qt.quick.wheel.target: QWheelEvent(Qt::ScrollUpdate, pixelDelta=QPoint(0,-5), angleDelta=QPoint(0,-10)) -> 
...
qt.quick.wheel.target: QWheelEvent(Qt::ScrollUpdate, pixelDelta=QPoint(0,1), angleDelta=QPoint(0,2)) -> StatusListView_QMLTYPE_267(0x600000ed7e90, parent=0x600000ed7d30, geometry=8,0 296x290)
qt.quick.wheel.target: QWheelEvent(Qt::ScrollUpdate, pixelDelta=QPoint(0,1), angleDelta=QPoint(0,2)) -> StatusListView_QMLTYPE_267(0x600000ed7e90, parent=0x600000ed7d30, geometry=8,0 296x290)
qt.quick.wheel.target: QWheelEvent(Qt::ScrollEnd) -> StatusListView_QMLTYPE_267(0x600000ed7e90, parent=0x600000ed7d30, geometry=8,0 296x290)
qt.quick.wheel.target: QWheelEvent(Qt::ScrollEnd) -> StatusListView_QMLTYPE_267(0x600000ed7e90, parent=0x600000ed7d30, geometry=8,0 296x290)

the output comes from qquickwindow.cpp from bool QQuickWindowPrivate::deliverSinglePointEventUntilAccepted(QQuickPointerEvent *event)

Furthermore, adding WheelHandler on top of ListView (intercepting wheel events) does little help, as in order for it to actually activate I have to pass acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad . Unfortunately setting

acceptedDevices: PointerDevice.Mouse
acceptedButtons: Qt.NoButton

Did not help

caybro commented 1 month ago

Look in StatusListView.qml, we do some non-standard stuff there, see if you can repro with a standard ListView

Seitseman commented 1 month ago

@caybro , I currently work with StatusListView, issues are the same as with ListView. It looks like the root cause is the implementation of Flickable or ListView: void QQuickFlickable::wheelEvent(QWheelEvent *event) in qtdeclarative/src/quick/items/qquickflickable.cpp or somewhere around void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)

Seitseman commented 1 month ago

Another approach was to check if there is any way to distinguish if particular wheel event came from actual wheel or from touchpad gesture. For that I've used both WheelHandler (with acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad ) and MouseArea. Checking what are the contents of the event passed through onWheel. Actual mouse wheel:

qml: ####@ event:  {"objectName":"","device":{"objectName":"","type":1,"pointerType":1,"capabilities":769,"maximumTouchPoints":1,"buttonCount":3,"name":"core pointer","uniqueId":{"numericId":0}},"modifiers":0,"button":0,"buttons":0,"angleDelta":{"x":0,"y":-170},"pixelDelta":{"x":0,"y":-85},"hasAngleDelta":true,"hasPixelDelta":true,"inverted":false}
qml: ####@ event:  {"objectName":"","device":{"objectName":"","type":1,"pointerType":1,"capabilities":769,"maximumTouchPoints":1,"buttonCount":3,"name":"core pointer","uniqueId":{"numericId":0}},"modifiers":0,"button":0,"buttons":0,"angleDelta":{"x":0,"y":-168},"pixelDelta":{"x":0,"y":-84},"hasAngleDelta":true,"hasPixelDelta":true,"inverted":false}
qml: ####@ event:  {"objectName":"","device":{"objectName":"","type":1,"pointerType":1,"capabilities":769,"maximumTouchPoints":1,"buttonCount":3,"name":"core pointer","uniqueId":{"numericId":0}},"modifiers":0,"button":0,"buttons":0,"angleDelta":{"x":0,"y":-168},"pixelDelta":{"x":0,"y":-84},"hasAngleDelta":true,"hasPixelDelta":true,"inverted":false}
qt.quick.handler.wheel: "" deactivating due to timeout

For TouchPad:

qml: ####@ event:  {"objectName":"","device":{"objectName":"","type":1,"pointerType":1,"capabilities":769,"maximumTouchPoints":1,"buttonCount":3,"name":"core pointer","uniqueId":{"numericId":0}},"modifiers":0,"button":0,"buttons":0,"angleDelta":{"x":-2,"y":-4},"pixelDelta":{"x":-1,"y":-2},"hasAngleDelta":true,"hasPixelDelta":true,"inverted":true}
qml: ####@ event:  {"objectName":"","device":{"objectName":"","type":1,"pointerType":1,"capabilities":769,"maximumTouchPoints":1,"buttonCount":3,"name":"core pointer","uniqueId":{"numericId":0}},"modifiers":0,"button":0,"buttons":0,"angleDelta":{"x":0,"y":0},"pixelDelta":{"x":0,"y":0},"hasAngleDelta":false,"hasPixelDelta":false,"inverted":true}
qml: ####@ event:  {"objectName":"","device":{"objectName":"","type":1,"pointerType":1,"capabilities":769,"maximumTouchPoints":1,"buttonCount":3,"name":"core pointer","uniqueId":{"numericId":0}},"modifiers":0,"button":0,"buttons":0,"angleDelta":{"x":-2,"y":-2},"pixelDelta":{"x":-1,"y":-1},"hasAngleDelta":true,"hasPixelDelta":true,"inverted":true}
qml: ####@ event:  {"objectName":"","device":{"objectName":"","type":1,"pointerType":1,"capabilities":769,"maximumTouchPoints":1,"buttonCount":3,"name":"core pointer","uniqueId":{"numericId":0}},"modifiers":0,"button":0,"buttons":0,"angleDelta":{"x":0,"y":0},"pixelDelta":{"x":0,"y":0},"hasAngleDelta":false,"hasPixelDelta":false,"inverted":true}
qml: ####@ event:  {"objectName":"","device":{"objectName":"","type":1,"pointerType":1,"capabilities":769,"maximumTouchPoints":1,"buttonCount":3,"name":"core pointer","uniqueId":{"numericId":0}},"modifiers":0,"button":0,"buttons":0,"angleDelta":{"x":-2,"y":-2},"pixelDelta":{"x":-1,"y":-1},"hasAngleDelta":true,"hasPixelDelta":true,"inverted":true}
qml: ####@ event:  {"objectName":"","device":{"objectName":"","type":1,"pointerType":1,"capabilities":769,"maximumTouchPoints":1,"buttonCount":3,"name":"core pointer","uniqueId":{"numericId":0}},"modifiers":0,"button":0,"buttons":0,"angleDelta":{"x":0,"y":0},"pixelDelta":{"x":0,"y":0},"hasAngleDelta":false,"hasPixelDelta":false,"inverted":true}
qml: ####@ event:  {"objectName":"","device":{"objectName":"","type":1,"pointerType":1,"capabilities":769,"maximumTouchPoints":1,"buttonCount":3,"name":"core pointer","uniqueId":{"numericId":0}},"modifiers":0,"button":0,"buttons":0,"angleDelta":{"x":0,"y":0},"pixelDelta":{"x":0,"y":0},"hasAngleDelta":false,"hasPixelDelta":false,"inverted":true}

Which means there is no way all Touch events could be "filtered out" and only real wheel processed in WheelHandler or MouseArea

Seitseman commented 1 month ago

There is https://bugreports.qt.io/browse/QTBUG-56075 and https://codereview.qt-project.org/c/qt/qtdeclarative/+/476967 That supposedly might have fixed logic how Qt's flickable calculate acceleration/deceleration of flicking/scrolling. But it seems its only integrated in Qt6. However, it looks to me that we could find some compromise for our usecase by using WheelHandler or MouseArea and have some sensible wheel/touchpad handling. Another approach is to check if Qt5 has some means to enable distinguishing between real wheel events and 'synthesized' .

caybro commented 1 month ago

There is https://bugreports.qt.io/browse/QTBUG-56075 and https://codereview.qt-project.org/c/qt/qtdeclarative/+/476967 That supposedly might have fixed logic how Qt's flickable calculate acceleration/deceleration of flicking/scrolling. But it seems its only integrated in Qt6. However, it looks to me that we could find some compromise for our usecase by using WheelHandler or MouseArea and have some sensible wheel/touchpad handling. Another approach is to check if Qt5 has some means to enable distinguishing between real wheel events and 'synthesized' .

I don't have a high hope for a fix to be available in Qt5

Seitseman commented 1 month ago

After discussions with @stefandunca , it was agreed that for the case of dApps list (this issue), we can allow the list to grow and take as much height as possible, thus allowing user to reach for more connected dApps without the need to scroll.