File: upstream_1b11b2e3_Use-KModifierKeyInfo-to-detect-lock-modifiers-status.patch

package info (click to toggle)
krdc 4%3A25.04.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 7,124 kB
  • sloc: cpp: 8,746; xml: 304; makefile: 6; sh: 5
file content (273 lines) | stat: -rw-r--r-- 8,202 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
From 1b11b2e3f51bbaea5fa10f3103006669a7b29145 Mon Sep 17 00:00:00 2001
From: Fabio Bas <ctrlaltca@gmail.com>
Date: Fri, 18 Jul 2025 16:20:07 +0200
Subject: [PATCH] Use KModifierKeyInfo to detect *lock modifiers' status

RDP: sync {caps,num,lock}lock keystate to remote session on start and at every focusIn

BUG: 349813
---
 CMakeLists.txt                                |  5 ++-
 core/CMakeLists.txt                           |  1 +
 core/remoteview.cpp                           | 34 +++++++++++++++++++
 core/remoteview.h                             | 16 +++++++++
 ...krdc.desktop => org.kde.krdc.desktop.cmake |  3 +-
 rdp/rdpsession.cpp                            | 24 +++++++++++++
 rdp/rdpsession.h                              |  2 ++
 rdp/rdpview.cpp                               |  9 +++++
 rdp/rdpview.h                                 |  1 +
 9 files changed, 93 insertions(+), 2 deletions(-)
 rename org.kde.krdc.desktop => org.kde.krdc.desktop.cmake (98%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e446da0a..d556e980 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,6 +51,7 @@ find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS
     I18n
     KIO
     Crash
+    GuiAddons
 )
 
 find_package(KF6StatusNotifierItem ${KF_MIN_VERSION} REQUIRED)
@@ -230,7 +231,9 @@ if (HAVE_KACTIVITIES)
 endif()
 
 install(TARGETS krdc ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
-install(PROGRAMS org.kde.krdc.desktop DESTINATION ${KDE_INSTALL_APPDIR})
+configure_file(org.kde.krdc.desktop.cmake ${CMAKE_CURRENT_BINARY_DIR}/org.kde.krdc.desktop @ONLY)
+
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.krdc.desktop DESTINATION ${KDE_INSTALL_APPDIR})
 install(FILES org.kde.krdc.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
 
 ecm_install_icons(
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index bb8e3b6c..85260d57 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -31,6 +31,7 @@ target_link_libraries(krdccore
     KF6::I18n
     KF6::ConfigGui
     KF6::Completion
+    KF6::GuiAddons
     Qt::Gui
     Qt::Widgets)
 
diff --git a/core/remoteview.cpp b/core/remoteview.cpp
index ef76ef3c..d912ae29 100644
--- a/core/remoteview.cpp
+++ b/core/remoteview.cpp
@@ -9,6 +9,9 @@
 #include "remoteview.h"
 #include "krdc_debug.h"
 
+#ifndef QTONLY
+#include <KModifierKeyInfo>
+#endif
 #include <QApplication>
 #include <QBitmap>
 #include <QEvent>
@@ -58,6 +61,10 @@ RemoteView::RemoteView(QWidget *parent)
     m_clipboard = QApplication::clipboard();
     connect(m_clipboard, &QClipboard::dataChanged, this, &RemoteView::localClipboardChanged);
 
+#ifndef QTONLY
+    m_modifierKeyInfo = new KModifierKeyInfo(this);
+#endif
+
 #ifdef HAVE_WAYLAND
     if (qGuiApp->platformName() == QLatin1String("wayland")) {
         m_inhibition.reset(new WaylandInhibition(window()->windowHandle()));
@@ -568,4 +575,31 @@ void RemoteView::sshErrorMessage(const QString &message)
     QWidget::releaseKeyboard();
 }
 
+bool RemoteView::isCapsLockEnabled()
+{
+#ifdef QTONLY
+    return false;
+#else
+    return m_modifierKeyInfo->isKeyLatched(Qt::Key_CapsLock) || m_modifierKeyInfo->isKeyLocked(Qt::Key_CapsLock);
+#endif
+}
+
+bool RemoteView::isNumLockEnabled()
+{
+#ifdef QTONLY
+    return false;
+#else
+    return m_modifierKeyInfo->isKeyLatched(Qt::Key_NumLock) || m_modifierKeyInfo->isKeyLocked(Qt::Key_NumLock);
+#endif
+}
+
+bool RemoteView::isScrollLockEnabled()
+{
+#ifdef QTONLY
+    return false;
+#else
+    return m_modifierKeyInfo->isKeyLatched(Qt::Key_ScrollLock) || m_modifierKeyInfo->isKeyLocked(Qt::Key_ScrollLock);
+#endif
+}
+
 #include "moc_remoteview.cpp"
diff --git a/core/remoteview.h b/core/remoteview.h
index c5bf3cbe..bf1483e4 100644
--- a/core/remoteview.h
+++ b/core/remoteview.h
@@ -36,6 +36,7 @@ struct ModifierKey {
 };
 
 class HostPreferences;
+class KModifierKeyInfo;
 
 /**
  * Generic widget that displays a remote framebuffer.
@@ -263,6 +264,19 @@ public:
      */
     virtual QPixmap takeScreenshot();
 
+    /**
+     * @return status of the caps lock key
+     */
+    bool isCapsLockEnabled();
+    /**
+     * @return status of the num lock key
+     */
+    bool isNumLockEnabled();
+    /**
+     * @return status of the scroll lock key
+     */
+    bool isScrollLockEnabled();
+
 #ifndef QTONLY
     /**
      * Returns the current host preferences of this view.
@@ -456,6 +470,8 @@ protected:
     qreal m_factor;
     QClipboard *m_clipboard;
     QMap<int, ModifierKey> m_modifiers;
+    KModifierKeyInfo *m_modifierKeyInfo;
+
 #ifdef HAVE_WAYLAND
     std::unique_ptr<ShortcutInhibition> m_inhibition;
 #endif
diff --git a/org.kde.krdc.desktop b/org.kde.krdc.desktop.cmake
similarity index 98%
rename from org.kde.krdc.desktop
rename to org.kde.krdc.desktop.cmake
index 29ab2e5c..3beb404c 100755
--- a/org.kde.krdc.desktop
+++ b/org.kde.krdc.desktop.cmake
@@ -1,7 +1,7 @@
 # KDE Config File
 [Desktop Entry]
 Type=Application
-Exec=krdc -qwindowtitle %c %u
+Exec=@CMAKE_INSTALL_PREFIX@/bin/krdc -qwindowtitle %c %u
 Icon=krdc
 Terminal=false
 Name=KRDC
@@ -180,3 +180,4 @@ X-DocPath=krdc/index.html
 StartupWMClass=krdc
 MimeType=x-scheme-handler/vnc;x-scheme-handler/rdp;application/x-krdc;
 Categories=Qt;KDE;Network;RemoteAccess;
+X-KDE-Wayland-Interfaces=org_kde_kwin_keystate
\ No newline at end of file
diff --git a/rdp/rdpsession.cpp b/rdp/rdpsession.cpp
index 25747609..3449092a 100644
--- a/rdp/rdpsession.cpp
+++ b/rdp/rdpsession.cpp
@@ -987,6 +987,10 @@ bool RdpSession::sendEvent(QEvent *event, QWidget *source)
     switch (event->type()) {
     case QEvent::KeyPress:
     case QEvent::KeyRelease: {
+        if (m_needKeyStateSync) {
+            m_needKeyStateSync = false;
+            syncKeyState();
+        }
         auto keyEvent = static_cast<QKeyEvent *>(event);
         const DWORD vc = GetVirtualKeyCodeFromKeycode(keyEvent->nativeScanCode(), WINPR_KEYCODE_TYPE_XKB);
         const DWORD code = GetVirtualScanCodeFromVirtualKeyCode(vc, WINPR_KBD_TYPE_IBM_ENHANCED);
@@ -1090,6 +1094,26 @@ bool RdpSession::sendEvent(QEvent *event, QWidget *source)
     return QObject::event(event);
 }
 
+bool RdpSession::syncKeyState()
+{
+    auto input = m_context.rdp->input;
+    if (!input) {
+        return false;
+    }
+
+    UINT16 flags = 0;
+
+    if (m_view->isCapsLockEnabled())
+        flags |= KBD_SYNC_CAPS_LOCK;
+    if (m_view->isNumLockEnabled())
+        flags |= KBD_SYNC_NUM_LOCK;
+    if (m_view->isScrollLockEnabled())
+        flags |= KBD_SYNC_SCROLL_LOCK;
+
+    qCDebug(KRDC) << "Sync key state: " << flags;
+    return freerdp_input_send_synchronize_event(input, flags);
+}
+
 void RdpSession::setState(RdpSession::State newState)
 {
     if (newState == m_state) {
diff --git a/rdp/rdpsession.h b/rdp/rdpsession.h
index 1caf25ae..61e42b60 100644
--- a/rdp/rdpsession.h
+++ b/rdp/rdpsession.h
@@ -103,6 +103,7 @@ public:
     void stop();
 
     bool sendEvent(QEvent *event, QWidget *source);
+    bool syncKeyState();
 
     void initializeClipboard(RdpContext *krdp, CliprdrClientContext *cliprdr);
     void initializeDisplay(RdpContext *krdp, DispClientContext *disp);
@@ -201,6 +202,7 @@ private:
     int m_port = -1;
     QSize m_size;
     bool m_firstPasswordTry;
+    bool m_needKeyStateSync = true;
 
     std::thread m_thread;
 
diff --git a/rdp/rdpview.cpp b/rdp/rdpview.cpp
index 1a32bd72..d4583584 100644
--- a/rdp/rdpview.cpp
+++ b/rdp/rdpview.cpp
@@ -512,4 +512,13 @@ void RdpView::handleLocalClipboardChanged(const QMimeData *data)
     if (m_session) {
         m_session->sendClipboard(data);
     }
-}
\ No newline at end of file
+}
+
+void RdpView::focusInEvent(QFocusEvent *event)
+{
+    if (m_session) {
+        m_session->syncKeyState();
+    }
+
+    RemoteView::focusInEvent(event);
+}
diff --git a/rdp/rdpview.h b/rdp/rdpview.h
index 996beecb..c5063125 100644
--- a/rdp/rdpview.h
+++ b/rdp/rdpview.h
@@ -75,6 +75,7 @@ protected:
     void handleWheelEvent(QWheelEvent *event) override;
     void handleMouseEvent(QMouseEvent *event) override;
     void handleLocalClipboardChanged(const QMimeData *data) override;
+    void focusInEvent(QFocusEvent *event) override;
 
 private:
     void onRectangleUpdated(const QRect &rect);
-- 
GitLab