krfb pointer scale workaround (AI-assisted, unreviewed) - KDE bugs 466276 / 524406
- Disclosure: written with AI assistance (Claude) to fix one machine (Fedora 45, Plasma 6.8.2, krfb 26.08.3, one monitor 2560x1440 at 125%). Tested on that setup only. Not a recommended fix; posted in case it helps. Context: KDE bugs 466276 (comment 13) and 524406.
- It may need small manual changes on other krfb versions (e.g. 26.04.x).
-
- --- a/events/xdp/xdpevents.cpp
- +++ b/events/xdp/xdpevents.cpp
- @@ -15,6 +15,10 @@
- #include <QApplication>
- #include <QGlobalStatic>
- +#include <QGuiApplication>
- +#include <QScreen>
- +#include <QSettings>
- +#include <QStandardPaths>
- class EventData
- {
- @@ -45,6 +49,40 @@
- QStringLiteral("/org/freedesktop/portal/desktop"), QDBusConnection::sessionBus()));
- }
- +// The VNC client reports pointer positions in framebuffer (physical) pixels, but the
- +// RemoteDesktop portal expects the compositor's logical (scaled) coordinates.
- +// Divide by the display scale. An optional override can be set in ~/.config/krfbrc:
- +// [General]
- +// pointerScale=1.25
- +// Without it, the scale is derived from the captured frame width and the logical screen width.
- +static qreal configuredPointerScale()
- +{
- + static const qreal value = []() -> qreal {
- + QSettings cfg(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/krfbrc"), QSettings::IniFormat);
- + bool ok = false;
- + const qreal v = cfg.value(QStringLiteral("pointerScale")).toDouble(&ok);
- + return (ok && v > 0) ? v : 0;
- + }();
- + return value;
- +}
- +
- +static qreal pointerScale(int frameBufferWidth)
- +{
- + const qreal configured = configuredPointerScale();
- + if (configured > 0) {
- + return configured;
- + }
- + // QScreen::devicePixelRatio() is rounded up to a whole number on Wayland (2 for a 1.25x
- + // output), so derive the scale from the captured frame width and the logical screen width.
- + if (const QScreen *screen = QGuiApplication::primaryScreen()) {
- + const int logicalWidth = screen->geometry().width();
- + if (logicalWidth > 0 && frameBufferWidth > 0) {
- + return qreal(frameBufferWidth) / logicalWidth;
- + }
- + }
- + return 1.0;
- +}
- +
- void XdpEventHandler::handleKeyboard(bool down, rfbKeySym keySym)
- {
- const QDBusObjectPath sessionHandle = frameBuffer()->customProperty(QStringLiteral("session_handle")).value<QDBusObjectPath>();
- @@ -61,7 +99,8 @@
- }
- if (x != data->x || y != data->y) {
- - data->dbusXdpRemoteDesktopService->NotifyPointerMotionAbsolute(sessionHandle, QVariantMap(), streamNodeId, x, y);
- + const qreal scale = pointerScale(frameBuffer()->width());
- + data->dbusXdpRemoteDesktopService->NotifyPointerMotionAbsolute(sessionHandle, QVariantMap(), streamNodeId, x / scale, y / scale);
- data->x = x;
- data->y = y;
- }