[pim/mimetreeparser] src/quick: Fix horizontal scroll too
Claudio Cambra <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 037c5b63e2c2d8565a530f56bdb2bc0d985c83bb by Claudio Cambra.
Committed on 16/08/2026 at 16:51.
Pushed by clau-cambra into branch 'master'.
Fix horizontal scroll too
Fix horizontal scroll
M +77 -64 src/quick/qml/private/HtmlPart.qml
M +49 -25 src/quick/wheelinterceptor.cpp
M +4 -0 src/quick/wheelinterceptor.h
https://invent.kde.org/pim/mimetreeparser/-/commit/037c5b63e2c2d8565a530f56bdb2bc0d985c83bb
diff --git a/src/quick/qml/private/HtmlPart.qml b/src/quick/qml/private/HtmlPart.qml
index c968345..4890334 100644
--- a/src/quick/qml/private/HtmlPart.qml
+++ b/src/quick/qml/private/HtmlPart.qml
@@ -27,82 +27,95 @@ Item {
htmlView.loadHtml(content, "file:///");
}
- QQC2.ScrollView {
+ Flickable {
+ id: flickable
anchors.fill: parent
- Flickable {
- id: flickable
+ clip: true
+ boundsBehavior: Flickable.StopAtBounds
+ contentWidth: root.contentWidth
- clip: true
- boundsBehavior: Flickable.StopAtBounds
+ WebEngineView {
+ id: htmlView
+ objectName: "htmlView"
+ anchors.fill: parent
- WebEngineView {
- id: htmlView
- objectName: "htmlView"
- anchors.fill: parent
-
- Component.onCompleted: loadHtml(content, "file:///")
- onLoadingChanged: loadingInfo => {
- if (loadingInfo.status === WebEngineView.LoadFailedStatus) {
- console.warn("Failed to load html content.")
- console.warn("Error is ", loadingInfo.errorString)
- }
- root.contentWidth = Math.max(contentsSize.width, flickable.minimumSize)
-
- if (loadingInfo.status === WebEngineView.LoadSucceededStatus) {
- runJavaScript("[document.body.scrollHeight, document.body.scrollWidth, document.documentElement.scrollHeight]", function(result) {
- root.contentHeight = Math.min(Math.max(result[0], result[2]), 4000);
- root.contentWidth = Math.min(Math.max(result[1], flickable.width), 2000)
- });
- }
- }
- onLinkHovered: hoveredUrl => {
- // Qt 6.6.1 needs to toString otherwise we get a compile error
- // https://bugreports.qt.io/browse/QTBUG-119165
- console.debug("Link hovered ", hoveredUrl.toString())
- }
- onNavigationRequested: request => {
- if (request.navigationType === WebEngineNavigationRequest.LinkClickedNavigation) {
- Qt.openUrlExternally(request.url)
- request.action = WebEngineNavigationRequest.IgnoreRequest
- }
+ Component.onCompleted: loadHtml(content, "file:///")
+ onLoadingChanged: loadingInfo => {
+ if (loadingInfo.status === WebEngineView.LoadFailedStatus) {
+ console.warn("Failed to load html content.")
+ console.warn("Error is ", loadingInfo.errorString)
}
- settings {
- webGLEnabled: false
- touchIconsEnabled: false
- spatialNavigationEnabled: false
- screenCaptureEnabled: false
- pluginsEnabled: false
- localStorageEnabled: false
- localContentCanAccessRemoteUrls: false
- localContentCanAccessFileUrls: false
- linksIncludedInFocusChain: false
- javascriptEnabled: true
- javascriptCanOpenWindows: false
- javascriptCanAccessClipboard: false
- hyperlinkAuditingEnabled: false
- fullScreenSupportEnabled: false
- errorPageEnabled: false
- //defaultTextEncoding: ???
- autoLoadImages: root.autoLoadImages
- autoLoadIconsForPage: false
- accelerated2dCanvasEnabled: false
- //The webview should not steal focus
- focusOnNavigationEnabled: false
+ root.contentWidth = Math.max(contentsSize.width, root.minimumSize)
+ if (loadingInfo.status === WebEngineView.LoadSucceededStatus) {
+ runJavaScript("[document.body.scrollHeight, document.body.scrollWidth, document.documentElement.scrollHeight]", function(result) {
+ root.contentHeight = Math.min(Math.max(result[0], result[2]), 4000);
+ root.contentWidth = Math.min(Math.max(result[1], root.width), 2000)
+ });
}
- profile {
- offTheRecord: true
- httpCacheType: WebEngineProfile.NoCache
- persistentCookiesPolicy: WebEngineProfile.NoPersistentCookies
- }
- onContextMenuRequested: request => {
- request.accepted = true
+ }
+ onLinkHovered: hoveredUrl => {
+ // Qt 6.6.1 needs to toString otherwise we get a compile error
+ // https://bugreports.qt.io/browse/QTBUG-119165
+ console.debug("Link hovered ", hoveredUrl.toString())
+ }
+ onNavigationRequested: request => {
+ if (request.navigationType === WebEngineNavigationRequest.LinkClickedNavigation) {
+ Qt.openUrlExternally(request.url)
+ request.action = WebEngineNavigationRequest.IgnoreRequest
}
}
+ settings {
+ webGLEnabled: false
+ touchIconsEnabled: false
+ spatialNavigationEnabled: false
+ screenCaptureEnabled: false
+ pluginsEnabled: false
+ localStorageEnabled: false
+ localContentCanAccessRemoteUrls: false
+ localContentCanAccessFileUrls: false
+ linksIncludedInFocusChain: false
+ javascriptEnabled: true
+ javascriptCanOpenWindows: false
+ javascriptCanAccessClipboard: false
+ hyperlinkAuditingEnabled: false
+ fullScreenSupportEnabled: false
+ errorPageEnabled: false
+ //defaultTextEncoding: ???
+ autoLoadImages: root.autoLoadImages
+ autoLoadIconsForPage: false
+ accelerated2dCanvasEnabled: false
+ //The webview should not steal focus
+ focusOnNavigationEnabled: false
+ }
+ profile {
+ offTheRecord: true
+ httpCacheType: WebEngineProfile.NoCache
+ persistentCookiesPolicy: WebEngineProfile.NoPersistentCookies
+ }
+ onContextMenuRequested: request => {
+ request.accepted = true
+ }
}
}
WheelInterceptor {
+ id: wheelInterceptor
source: htmlView
target: flickable
}
+
+ QQC2.ScrollBar {
+ id: hScrollBar
+ orientation: Qt.Horizontal
+ parent: wheelInterceptor.scrollTarget ? wheelInterceptor.scrollTarget : root
+ anchors.left: parent ? parent.left : undefined
+ anchors.right: parent ? parent.right : undefined
+ anchors.bottom: parent ? parent.bottom : undefined
+ visible: root.contentWidth > root.width
+ size: root.width / Math.max(1, root.contentWidth)
+ position: flickable.contentX / Math.max(1, root.contentWidth - root.width)
+ onPositionChanged: flickable.contentX = position * (root.contentWidth - root.width)
+ }
+
+ Component.onCompleted: wheelInterceptor.hScrollBar = hScrollBar
}
diff --git a/src/quick/wheelinterceptor.cpp b/src/quick/wheelinterceptor.cpp
index a99114c..e097e81 100644
--- a/src/quick/wheelinterceptor.cpp
+++ b/src/quick/wheelinterceptor.cpp
@@ -5,6 +5,7 @@
#include <QCoreApplication>
#include <QGuiApplication>
+#include <QMetaObject>
#include <QStyleHints>
#include <QWheelEvent>
@@ -38,7 +39,6 @@ QQuickItem *WheelInterceptor::target() const
{
return m_target;
}
-
void WheelInterceptor::setTarget(QQuickItem *target)
{
if (m_target == target) {
@@ -48,6 +48,11 @@ void WheelInterceptor::setTarget(QQuickItem *target)
Q_EMIT targetChanged();
}
+QQuickItem *WheelInterceptor::scrollTarget() const
+{
+ return m_scrollTarget;
+}
+
void WheelInterceptor::updateScrollTarget()
{
m_scrollTarget = nullptr;
@@ -63,34 +68,53 @@ void WheelInterceptor::updateScrollTarget()
current = current->parentItem();
}
- if (!m_scrollTarget && m_target) {
- current = m_target;
- while (current) {
- if (current->inherits("QQuickFlickable")) {
- m_scrollTarget = current;
- }
- current = current->parentItem();
- }
- }
+ Q_EMIT scrollTargetChanged();
+}
+
+static void applyScroll(QQuickItem *target, qreal pixelDelta)
+{
+ const auto viewH = target->height();
+ const auto contentH = target->property("contentHeight").toReal();
+ const auto currentY = target->property("contentY").toReal();
+ const auto maxScrollY = qMax(0.0, contentH - viewH);
+ target->setProperty("contentY", qBound(0.0, currentY + pixelDelta, maxScrollY));
+}
+
+static void applyHScroll(QQuickItem *target, qreal pixelDelta)
+{
+ const auto viewW = target->width();
+ const auto contentW = target->property("contentWidth").toReal();
+ const auto currentX = target->property("contentX").toReal();
+ const auto maxScrollX = qMax(0.0, contentW - viewW);
+ target->setProperty("contentX", qBound(0.0, currentX + pixelDelta, maxScrollX));
}
bool WheelInterceptor::eventFilter(QObject *obj, QEvent *event)
{
Q_UNUSED(obj);
- if (event->type() == QEvent::Wheel && m_source && m_scrollTarget) {
- auto wheelEvent = static_cast<QWheelEvent *>(event);
- const auto localPos = m_source->mapFromGlobal(wheelEvent->globalPosition().toPoint());
- if (m_source->contains(localPos)) {
- const auto viewH = m_scrollTarget->height();
- const auto contentH = m_scrollTarget->property("contentHeight").toReal();
- const auto currentY = m_scrollTarget->property("contentY").toReal();
- const auto maxScroll = qMax(0.0, contentH - viewH);
- const auto delta = wheelEvent->angleDelta().y();
- const auto scrollLines = QGuiApplication::styleHints()->wheelScrollLines();
- const auto pixels = -(delta / 120.0) * scrollLines * 20.0;
- m_scrollTarget->setProperty("contentY", qBound(0.0, currentY + pixels, maxScroll));
- return true;
- }
+ if (event->type() != QEvent::Wheel || !m_source) {
+ return false;
+ }
+ auto wheelEvent = static_cast<QWheelEvent *>(event);
+ const auto localPos = m_source->mapFromGlobal(wheelEvent->globalPosition().toPoint());
+ if (!m_source->contains(localPos)) {
+ return false;
+ }
+
+ const auto scrollLines = QGuiApplication::styleHints()->wheelScrollLines();
+ const auto factor = scrollLines * 20.0 / 120.0;
+ const auto deltaY = -wheelEvent->angleDelta().y() * factor;
+ const auto deltaX = -wheelEvent->angleDelta().x() * factor;
+
+ if (m_target) {
+ applyScroll(m_target, deltaY);
+ applyHScroll(m_target, deltaX);
+ } else if (deltaX != 0.0) {
+ const auto js = QStringLiteral("window.scrollBy(%1, 0)").arg(deltaX);
+ QMetaObject::invokeMethod(m_source, "runJavaScript", Q_ARG(QString, js));
+ }
+ if (m_scrollTarget) {
+ applyScroll(m_scrollTarget, deltaY);
}
- return false;
+ return true;
}
diff --git a/src/quick/wheelinterceptor.h b/src/quick/wheelinterceptor.h
index 6b0650f..bbdfc63 100644
--- a/src/quick/wheelinterceptor.h
+++ b/src/quick/wheelinterceptor.h
@@ -13,6 +13,7 @@ class WheelInterceptor : public QObject
QML_ELEMENT
Q_PROPERTY(QQuickItem *source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QQuickItem *scrollTarget READ scrollTarget NOTIFY scrollTargetChanged)
public:
explicit WheelInterceptor(QObject *parent = nullptr);
@@ -23,12 +24,15 @@ public:
QQuickItem *target() const;
void setTarget(QQuickItem *target);
+ QQuickItem *scrollTarget() const;
+
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
Q_SIGNALS:
void sourceChanged();
void targetChanged();
+ void scrollTargetChanged();
private:
void updateScrollTarget();