Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package krdp6 for openSUSE:Factory checked 
in at 2026-03-04 21:04:29
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/krdp6 (Old)
 and      /work/SRC/openSUSE:Factory/.krdp6.new.561 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "krdp6"

Wed Mar  4 21:04:29 2026 rev:35 rq:1336099 version:6.6.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/krdp6/krdp6.changes      2026-02-27 
17:09:06.270112260 +0100
+++ /work/SRC/openSUSE:Factory/.krdp6.new.561/krdp6.changes     2026-03-04 
21:04:33.702807314 +0100
@@ -1,0 +2,14 @@
+Tue Mar  3 12:26:45 UTC 2026 - Fabian Vogt <[email protected]>
+
+- Update to 6.6.2:
+  * New bugfix release
+  * For more details see https://kde.org/announcements/plasma/6/6.6.2
+- Changes since 6.6.1:
+  * Update version for new release 6.6.2
+  * Fix thread safety issues in VideoStream
+  * Fix potential deadlock in RdpConnection destructor
+  * Fix PortalSession destructor crash and resource leak
+  * Handle GFX CapsAdvertise re-advertisement from Windows clients
+  * Fix scroll wheel for RDP clients sending high-resolution or zero-position 
events (kde#511029)
+
+-------------------------------------------------------------------

Old:
----
  krdp-6.6.1.tar.xz
  krdp-6.6.1.tar.xz.sig

New:
----
  krdp-6.6.2.tar.xz
  krdp-6.6.2.tar.xz.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ krdp6.spec ++++++
--- /var/tmp/diff_new_pack.bNX7Bq/_old  2026-03-04 21:04:34.350834089 +0100
+++ /var/tmp/diff_new_pack.bNX7Bq/_new  2026-03-04 21:04:34.350834089 +0100
@@ -27,7 +27,7 @@
 %{!?_plasma6_version: %define _plasma6_version %(echo %{_plasma6_bugfix} | awk 
-F. '{print $1"."$2}')}
 %bcond_without released
 Name:           krdp6
-Version:        6.6.1
+Version:        6.6.2
 Release:        0
 Summary:        RDP Server for Plasma
 License:        LGPL-2.1-or-later

++++++ krdp-6.6.1.tar.xz -> krdp-6.6.2.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/krdp-6.6.1/CMakeLists.txt 
new/krdp-6.6.2/CMakeLists.txt
--- old/krdp-6.6.1/CMakeLists.txt       2026-02-24 10:38:15.000000000 +0100
+++ new/krdp-6.6.2/CMakeLists.txt       2026-03-03 10:31:18.000000000 +0100
@@ -1,7 +1,7 @@
 # SPDX-FileCopyrightText: 2023 Arjen Hiemstra <[email protected]>
 # SPDX-License-Identifier: BSD-2-Clause
 
-set(PROJECT_VERSION "6.6.1")
+set(PROJECT_VERSION "6.6.2")
 
 cmake_minimum_required(VERSION 3.16)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/krdp-6.6.1/po/nn/kcm_krdpserver.po 
new/krdp-6.6.2/po/nn/kcm_krdpserver.po
--- old/krdp-6.6.1/po/nn/kcm_krdpserver.po      2026-02-24 10:38:15.000000000 
+0100
+++ new/krdp-6.6.2/po/nn/kcm_krdpserver.po      2026-03-03 10:31:18.000000000 
+0100
@@ -5,7 +5,7 @@
 "Project-Id-Version: krdp\n"
 "Report-Msgid-Bugs-To: https://bugs.kde.org\n";
 "POT-Creation-Date: 2026-01-17 02:38+0000\n"
-"PO-Revision-Date: 2024-08-08 22:05+0200\n"
+"PO-Revision-Date: 2026-03-01 19:51+0100\n"
 "Last-Translator: Karl Ove Hufthammer <[email protected]>\n"
 "Language-Team: Norwegian Nynorsk <[email protected]>\n"
 "Language: nn\n"
@@ -13,7 +13,7 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Lokalize 24.11.70\n"
+"X-Generator: Lokalize 26.03.70\n"
 "X-Environment: kde\n"
 "X-Accelerator-Marker: &\n"
 "X-Text-Markup: kde4\n"
@@ -58,7 +58,7 @@
 #: krdpserversettings.kcfg:35
 #, kde-format
 msgid "Whether the current user can log in via PAM"
-msgstr ""
+msgstr "Om gjeldande brukar kan logga inn via PAM"
 
 #. i18n: ectx: label, entry (Autostart), group (General)
 #: krdpserversettings.kcfg:39
@@ -165,7 +165,7 @@
 #, kde-format
 msgctxt "@info:status"
 msgid "Systemd not found. krdpserver will require manual activation."
-msgstr ""
+msgstr "Fann ikkje Systemd. krdpserver krev manuell aktivering."
 
 #: ui/main.qml:129
 #, kde-kuit-format
@@ -273,23 +273,23 @@
 msgstr ""
 
 #: ui/main_phone.qml:105
-#, fuzzy, kde-format
+#, kde-format
 msgctxt "@option:check"
 msgid "Enable RDP Server"
 msgstr "Bruk RDP-tenar"
 
 #: ui/main_phone.qml:128
-#, fuzzy, kde-format
+#, kde-format
 msgid "Hostname:"
-msgstr "Brukarnamn:"
+msgstr "Vertsnamn:"
 
 #: ui/main_phone.qml:134
-#, fuzzy, kde-format
+#, kde-format
 msgid "Use any of the following addresses to connect to this device:"
 msgstr "Bruk ei av desse adressene til å kopla til eininga:"
 
 #: ui/main_phone.qml:172
-#, fuzzy, kde-format
+#, kde-format
 msgctxt "@title:group"
 msgid "Server Settings"
 msgstr "Tenarinnstillingar"
@@ -343,19 +343,19 @@
 #, kde-format
 msgctxt "@title:group"
 msgid "System Users"
-msgstr ""
+msgstr "Systembrukarar"
 
 #: ui/UserListView.qml:49
 #, kde-format
 msgctxt "@title:group"
 msgid "Other Users"
-msgstr ""
+msgstr "Andre brukarar"
 
 #: ui/UserListView.qml:67
 #, kde-format
 msgctxt "@info:usagetip used as a subtitle for a title+subtitle list item"
 msgid "Login with your system password"
-msgstr ""
+msgstr "Logg inn med systempassord"
 
 #: ui/UserListView.qml:99
 #, kde-format
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/krdp-6.6.1/src/InputHandler.cpp 
new/krdp-6.6.2/src/InputHandler.cpp
--- old/krdp-6.6.1/src/InputHandler.cpp 2026-02-24 10:38:15.000000000 +0100
+++ new/krdp-6.6.2/src/InputHandler.cpp 2026-03-03 10:31:18.000000000 +0100
@@ -75,6 +75,7 @@
 public:
     RdpConnection *session;
     rdpInput *input;
+    QPointF lastMousePosition;
 };
 
 InputHandler::InputHandler(KRdp::RdpConnection *session)
@@ -108,6 +109,12 @@
 {
     QPointF position = QPointF(x, y);
 
+    // Track last known mouse position for wheel events from clients
+    // that send (0,0) as the position (e.g. Microsoft Remote Desktop)
+    if (flags & PTR_FLAGS_MOVE) {
+        d->lastMousePosition = position;
+    }
+
     Qt::MouseButton button = Qt::NoButton;
     if (flags & PTR_FLAGS_BUTTON1) {
         button = Qt::LeftButton;
@@ -118,19 +125,39 @@
     }
 
     if (flags & PTR_FLAGS_WHEEL || flags & PTR_FLAGS_HWHEEL) {
+        // Use last known mouse position if the client sends (0,0)
+        if (position.isNull() && !d->lastMousePosition.isNull()) {
+            position = d->lastMousePosition;
+        }
         auto axis = flags & WheelRotationMask;
         if (axis & PTR_FLAGS_WHEEL_NEGATIVE) {
             axis = (~axis & WheelRotationMask) + 1;
         }
         axis *= flags & PTR_FLAGS_WHEEL_NEGATIVE ? 1 : -1;
+        // The RDP protocol uses 120 units per standard wheel notch
+        // (15 degrees of rotation). Dividing by 8 converts to degrees,
+        // which we store in pixelDelta as a continuous scroll value.
+        auto degrees = axis / 8.0;
         if (flags & PTR_FLAGS_WHEEL) {
-            auto event =
-                std::make_shared<QWheelEvent>(position, QPointF{}, QPoint{}, 
QPoint{0, axis}, Qt::NoButton, Qt::KeyboardModifiers{}, Qt::NoScrollPhase, 
false);
+            auto event = std::make_shared<QWheelEvent>(position,
+                                                       QPointF{},
+                                                       QPoint{0, 
qRound(degrees)},
+                                                       QPoint{0, axis},
+                                                       Qt::NoButton,
+                                                       Qt::KeyboardModifiers{},
+                                                       Qt::NoScrollPhase,
+                                                       false);
             Q_EMIT inputEvent(event);
         }
         if (flags & PTR_FLAGS_HWHEEL) {
-            auto event =
-                std::make_shared<QWheelEvent>(position, QPointF{}, QPoint{}, 
QPoint{-axis, 0}, Qt::NoButton, Qt::KeyboardModifiers{}, Qt::NoScrollPhase, 
false);
+            auto event = std::make_shared<QWheelEvent>(position,
+                                                       QPointF{},
+                                                       
QPoint{qRound(-degrees), 0},
+                                                       QPoint{-axis, 0},
+                                                       Qt::NoButton,
+                                                       Qt::KeyboardModifiers{},
+                                                       Qt::NoScrollPhase,
+                                                       false);
             Q_EMIT inputEvent(event);
         }
         return true;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/krdp-6.6.1/src/PlasmaScreencastV1Session.cpp 
new/krdp-6.6.2/src/PlasmaScreencastV1Session.cpp
--- old/krdp-6.6.1/src/PlasmaScreencastV1Session.cpp    2026-02-24 
10:38:15.000000000 +0100
+++ new/krdp-6.6.2/src/PlasmaScreencastV1Session.cpp    2026-03-03 
10:31:18.000000000 +0100
@@ -229,12 +229,16 @@
     }
     case QEvent::Wheel: {
         auto we = std::static_pointer_cast<QWheelEvent>(event);
-        auto delta = we->angleDelta();
+        auto delta = we->pixelDelta();
+        // pixelDelta contains the scroll value already converted to
+        // degrees by InputHandler, preserving sub-notch precision
+        // from clients that send high-resolution wheel values
+        // (e.g. Microsoft Remote Desktop).
         if (delta.y() != 0) {
-            d->remoteInterface->axis(WL_POINTER_AXIS_VERTICAL_SCROLL, 
delta.y() / 120);
+            d->remoteInterface->axis(WL_POINTER_AXIS_VERTICAL_SCROLL, 
wl_fixed_from_double(delta.y()));
         }
         if (delta.x() != 0) {
-            d->remoteInterface->axis(WL_POINTER_AXIS_HORIZONTAL_SCROLL, 
delta.x() / 120);
+            d->remoteInterface->axis(WL_POINTER_AXIS_HORIZONTAL_SCROLL, 
wl_fixed_from_double(delta.x()));
         }
         break;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/krdp-6.6.1/src/PortalSession.cpp 
new/krdp-6.6.2/src/PortalSession.cpp
--- old/krdp-6.6.1/src/PortalSession.cpp        2026-02-24 10:38:15.000000000 
+0100
+++ new/krdp-6.6.2/src/PortalSession.cpp        2026-03-03 10:31:18.000000000 
+0100
@@ -127,6 +127,11 @@
 
 PortalSession::~PortalSession()
 {
+    if (d->sessionPath.path().isEmpty()) {
+        qCDebug(KRDP) << "No portal session to close (session was never 
created)";
+        return;
+    }
+
     // Make sure to clear any modifier keys that were pressed when the session 
closed, otherwise
     // we risk those keys getting stuck and the original session becoming 
unusable.
     for (auto keycode : {KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, 
KEY_RIGHTSHIFT, KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTMETA, KEY_RIGHTMETA}) {
@@ -186,13 +191,12 @@
     }
     case QEvent::Wheel: {
         auto we = std::static_pointer_cast<QWheelEvent>(event);
-        auto delta = we->angleDelta();
-        if (delta.y() != 0) {
-            d->remoteInterface->NotifyPointerAxisDiscrete(d->sessionPath, 
QVariantMap{}, 0 /* Vertical */, delta.y() / 120);
-        }
-        if (delta.x() != 0) {
-            d->remoteInterface->NotifyPointerAxisDiscrete(d->sessionPath, 
QVariantMap{}, 1 /* Horizontal */, delta.x() / 120);
-        }
+        auto delta = we->pixelDelta();
+        // pixelDelta contains the scroll value already converted to
+        // degrees by InputHandler. The vertical axis is negated to
+        // account for the sign convention in
+        // xdg-desktop-portal-kde's requestPointerAxis.
+        d->remoteInterface->NotifyPointerAxis(d->sessionPath, QVariantMap{}, 
delta.x(), -delta.y());
         break;
     }
     case QEvent::KeyPress:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/krdp-6.6.1/src/RdpConnection.cpp 
new/krdp-6.6.2/src/RdpConnection.cpp
--- old/krdp-6.6.1/src/RdpConnection.cpp        2026-02-24 10:38:15.000000000 
+0100
+++ new/krdp-6.6.2/src/RdpConnection.cpp        2026-03-03 10:31:18.000000000 
+0100
@@ -237,7 +237,11 @@
 
 RdpConnection::~RdpConnection()
 {
-    if (d->state == State::Streaming) {
+    // Close the peer first to unblock WaitForMultipleObjects in the
+    // run thread. Without this, thread.join() can deadlock when the
+    // session is not in the Streaming state but the thread is still
+    // blocked waiting for socket events.
+    if (d->peer) {
         d->peer->Close(d->peer);
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/krdp-6.6.1/src/VideoStream.cpp 
new/krdp-6.6.2/src/VideoStream.cpp
--- old/krdp-6.6.1/src/VideoStream.cpp  2026-02-24 10:38:15.000000000 +0100
+++ new/krdp-6.6.2/src/VideoStream.cpp  2026-03-03 10:31:18.000000000 +0100
@@ -128,8 +128,10 @@
     QQueue<VideoFrame> frameQueue;
     QSet<uint32_t> pendingFrames;
 
+    std::mutex pendingFramesMutex;
+
     int maximumFrameRate = 120;
-    int requestedFrameRate = 60;
+    std::atomic_int requestedFrameRate = 60;
     QQueue<FrameRateEstimate> frameRateEstimates;
     clk::system_clock::time_point lastFrameRateEstimation;
 
@@ -146,6 +148,7 @@
 
 VideoStream::~VideoStream()
 {
+    close();
 }
 
 bool VideoStream::initialize()
@@ -179,6 +182,14 @@
 
     d->frameSubmissionThread = std::jthread([this](std::stop_token token) {
         while (!token.stop_requested()) {
+            // Don't dequeue frames until the GFX channel is ready.
+            // This preserves the I-frame (keyframe) in the queue until
+            // CapsAdvertise has completed and we can actually send it.
+            if (!d->gfxContext || !d->capsConfirmed) {
+                std::this_thread::sleep_for(std::chrono::milliseconds(16));
+                continue;
+            }
+
             VideoFrame nextFrame;
             {
                 std::unique_lock lock(d->frameQueueMutex);
@@ -187,7 +198,7 @@
                 }
             }
             if (nextFrame.size.isEmpty()) {
-                std::this_thread::sleep_for(std::chrono::milliseconds(1000) / 
d->requestedFrameRate);
+                std::this_thread::sleep_for(std::chrono::milliseconds(1000) / 
d->requestedFrameRate.load());
                 continue;
             }
             sendFrame(nextFrame);
@@ -205,13 +216,25 @@
         return;
     }
 
-    d->gfxContext->Close(d->gfxContext.get());
-
+    // Stop the frame submission thread first to prevent
+    // use-after-free on gfxContext during close.
     if (d->frameSubmissionThread.joinable()) {
         d->frameSubmissionThread.request_stop();
         d->frameSubmissionThread.join();
     }
 
+    {
+        std::lock_guard lock(d->pendingFramesMutex);
+        d->pendingFrames.clear();
+    }
+    {
+        std::lock_guard lock(d->frameQueueMutex);
+        d->frameQueue.clear();
+    }
+
+    d->gfxContext->Close(d->gfxContext.get());
+    d->gfxContext.reset();
+
     Q_EMIT closed();
 }
 
@@ -259,6 +282,18 @@
 
 uint32_t VideoStream::onCapsAdvertise(const RDPGFX_CAPS_ADVERTISE_PDU 
*capsAdvertise)
 {
+    // Windows clients (mstsc) send CapsAdvertise twice: once during
+    // initial setup and again after confirming. If we already confirmed
+    // caps, this is a GFX channel reset — clear surface state so
+    // surfaces get re-created on the next frame.
+    if (d->capsConfirmed) {
+        qCDebug(KRDP) << "GFX channel reset (re-advertisement), resetting 
surface state";
+        d->capsConfirmed = false;
+        d->pendingReset = true;
+        d->surface = Surface{};
+        d->pendingFrames.clear();
+    }
+
     auto capsSets = capsAdvertise->capsSets;
     auto count = capsAdvertise->capsSetCount;
 
@@ -332,6 +367,8 @@
 {
     auto id = frameAcknowledge->frameId;
 
+    std::lock_guard lock(d->pendingFramesMutex);
+
     auto itr = d->pendingFrames.constFind(id);
     if (itr == d->pendingFrames.cend()) {
         qCWarning(KRDP) << "Got frame acknowledge for an unknown frame";
@@ -405,7 +442,10 @@
 
     d->encodedFrames++;
 
-    d->pendingFrames.insert(frameId);
+    {
+        std::lock_guard lock(d->pendingFramesMutex);
+        d->pendingFrames.insert(frameId);
+    }
 
     RDPGFX_START_FRAME_PDU startFramePdu;
     RDPGFX_END_FRAME_PDU endFramePdu;

Reply via email to