Fix stuck modifier keys after Alt+Tab in RDP remote desktop (#330) (#7878)

When the browser loses focus during an Alt+Tab, the RDP clients send the modifier key-down but never the key-up, leaving the modifier held on the remote machine (e.g. the next Enter becomes Alt+Enter and toggles the Windows console to fullscreen). The agent-desktop viewer was fixed for this long ago, but the RDP clients (agent-rdp and mstsc) were not. Release the modifier keys (L/R Shift, Ctrl, Alt, Win) on window 'blur' in both RDP clients so a dropped key-up can't get stuck. Co-authored-by: Steve E. Brown <> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

speedbrown committed Jun 7, 2026 at 11:22 UTC fd44a38c9dfdbbde872f6c3f95b13f6c49378e5c
2 files changed +16
public/mstsc/client.js
+7
@@ -141,6 +141,13 @@
141 return false;
142 });
143
144 + window.addEventListener('blur', function () {
145 + if (!self.socket || !self.activeSession) return;
146 + // Release modifiers so they can't get stuck on the remote after an Alt+Tab (issue #330).
147 + var mods = [42, 54, 29, 57373, 56, 57400, 57435, 57436];
148 + for (var i = 0; i < mods.length; i++) { self.socket.send(JSON.stringify(['scancode', mods[i], false])); }
149 + });
150 +
151 return this;
152 },
153 /**
public/scripts/agent-rdp-0.0.1.js
+9
@@ -125,10 +125,12 @@ var CreateRDPDesktop = function (canvasid, domainUrl) {
125 }
126 };
127 obj.socket.onclose = function () { changeState(0); };
128 + window.addEventListener('blur', obj.m.releaseModifiers);
129 changeState(1);
130 }
131
132 obj.Stop = function () {
133 + window.removeEventListener('blur', obj.m.releaseModifiers);
134 obj.Canvas.fillRect(0, 0, obj.ScreenWidth, obj.ScreenHeight);
135 if (obj.socket) { obj.socket.close(); }
136 }
@@ -201,6 +203,13 @@ var CreateRDPDesktop = function (canvasid, domainUrl) {
203 e.preventDefault();
204 return false;
205 }
206 + obj.m.releaseModifiers = function () {
207 + if (!obj.socket || (obj.State != 3)) return;
208 + // Release modifier keys so they can't get stuck on the remote when the browser loses
209 + // focus during an Alt+Tab (issue #330). L/R Shift, L/R Ctrl, L/R Alt, L/R Win.
210 + var mods = [42, 54, 29, 57373, 56, 57400, 57435, 57436];
211 + for (var i = 0; i < mods.length; i++) { obj.socket.send(JSON.stringify(['scancode', mods[i], false])); }
212 + }
213 obj.m.mousewheel = function (e) {
214 if (!obj.socket || (obj.State != 3)) return;
215 var m = getMousePosition(e);