[education/rkward] rkward/windows: Implement scrolling

Thomas Friedrichsmeier null at kde.org
Thu Apr 9 20:44:24 BST 2026


Git commit 2c09bb4d760e6f667f8f65a6099f54a1720a0f0d by Thomas Friedrichsmeier.
Committed on 09/04/2026 at 19:44.
Pushed by tfry into branch 'master'.

Implement scrolling

M  +10   -7    rkward/windows/rkqwebview.cpp
M  +2    -0    rkward/windows/rkqwebview.h
M  +10   -0    rkward/windows/rkqwebview.js

https://invent.kde.org/education/rkward/-/commit/2c09bb4d760e6f667f8f65a6099f54a1720a0f0d

diff --git a/rkward/windows/rkqwebview.cpp b/rkward/windows/rkqwebview.cpp
index 0ac24e0a4..4e046b75f 100644
--- a/rkward/windows/rkqwebview.cpp
+++ b/rkward/windows/rkqwebview.cpp
@@ -112,12 +112,6 @@ QWidget *RKQWebView::createWidget() {
 	connect(webView(), SIGNAL(pageUrlChanged(const QUrl &, const QString &, int)), this, SLOT(onUrlChanged(const QUrl &, const QString &, int)));
 	connect(webView(), SIGNAL(loadFinished(const QUrl &)), this, SLOT(onLoadFinished(const QUrl &)));
 	connect(webView(), SIGNAL(runJSResult(const QVariant &)), this, SLOT(onRunJSResult(const QVariant &)));
-	/* TODO: we may need to inject a script along the lines below for handling target=new
-	    and page internal navigation?
-	RKHTMLViewer::runJS(u"document.addEventListener('click', e => {"
-	    "  const origin = e.target.closest('a');"
-	    "  if (origin) alert(origin.href);"
-	    "})\n"_s); */
 	return view;
 }
 
@@ -208,6 +202,7 @@ void RKQWebView::findRequest(const QString &text, bool backwards, RKFindBar *fin
 
 QMenu *RKQWebView::createContextMenu(const QPoint &clickpos) {
 	RK_TRACE(APP);
+	// TODO
 	return new QMenu();
 }
 
@@ -228,6 +223,10 @@ void RKQWebView::receivedCallbackMessage(const QString &message) {
 			selected_text = sel;
 			Q_EMIT selectionChanged(!sel.isEmpty());
 		}
+	} else if (msg == "scroll"_L1) {
+		scroll_pos = QPoint(args["x"_L1].toInt(), args["y"_L1].toInt());
+	} else if (msg == "pageInternalNav"_L1) {
+		Q_EMIT pageInternalNavigation(QUrl(args["href"_L1].toString()));
 	} else {
 		RK_DEBUG(APP, DL_ERROR, "Non-recognized message %s", qPrintable(message));
 	}
@@ -239,22 +238,26 @@ void RKQWebView::exportPage() {
 
 QPoint RKQWebView::scrollPosition() const {
 	RK_TRACE(APP);
-	return QPoint();
+	return scroll_pos;
 }
 
 void RKQWebView::setScrollPosition(const QPoint &pos, bool wait_for_load) {
 	RK_TRACE(APP);
+	runJS(u"window.scroll({top: %1, left: %2, behavior: 'instant'});"_s.arg(pos.y(), pos.x()));
 }
 
 bool RKQWebView::supportsContentType(const QString &mimename) {
 	RK_TRACE(APP);
+	// TODO
 	return true;
 }
 
 void RKQWebView::zoomIn() {
 	RK_TRACE(APP);
+	// TODO
 }
 
 void RKQWebView::zoomOut() {
 	RK_TRACE(APP);
+	// TODO
 }
diff --git a/rkward/windows/rkqwebview.h b/rkward/windows/rkqwebview.h
index c6b73ada5..d37a8c126 100644
--- a/rkward/windows/rkqwebview.h
+++ b/rkward/windows/rkqwebview.h
@@ -9,6 +9,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #define RKQWEBVIEW_H
 
 #include <QMap>
+#include <QPoint>
 #include <QPointer>
 
 #include "rkhtmlviewer.h"
@@ -55,6 +56,7 @@ class RKQWebView : public RKHTMLViewer {
 	void tryRunNextScript();
 	void receivedCallbackMessage(const QString &message);
 	QString selected_text;
+	QPoint scroll_pos;
   private Q_SLOTS:
 	void onUrlChanged(const QUrl &url, const QString &error, int status);
 	void onLoadFinished(const QUrl &url);
diff --git a/rkward/windows/rkqwebview.js b/rkward/windows/rkqwebview.js
index 3c9473e6f..79b465563 100644
--- a/rkward/windows/rkqwebview.js
+++ b/rkward/windows/rkqwebview.js
@@ -15,6 +15,10 @@ document.onselectionchange = __rkward_debounce(function() {
 	__rkward_sendMessage("selChanged", { sel: document.getSelection().toString() });
 });
 
+document.onscroll = __rkward_debounce(function() {
+	__rkward_sendMessage("scroll", { x: window.scrollX, y: window.scrollY });
+});
+
 function __rkward_sendMessage(msg, args) {
 	if (__rkward.readyState == WebSocket.CONNECTING) {
 		setTimeout(__rkward_sendMessage.bind(null, msg, args), 10);
@@ -22,3 +26,9 @@ function __rkward_sendMessage(msg, args) {
 		__rkward.send(JSON.stringify({msg, args}));
 	}
 }
+
+document.addEventListener('click', e => {
+	const origin = e.target.closest('a');
+	if (origin && origin.href.startswith('#')) {
+		__rkward_sendMessage("pageInternalNav", { url: origin.href });
+});



More information about the rkward-tracker mailing list