Copilot commented on code in PR #12187:
URL: https://github.com/apache/cloudstack/pull/12187#discussion_r2588271030


##########
systemvm/agent/noVNC/app/ui.js:
##########
@@ -1740,6 +1753,51 @@ const UI = {
         UI.idleControlbar();
     },
 
+    _sendKeyUp(keysym, code) {

Review Comment:
   Missing null check for `UI.rfb` before calling `sendKey()`. If the RFB 
connection is not initialized, this will throw a runtime error. Add a check 
like `if (!UI.rfb) return;` at the beginning of the method, consistent with 
other methods in this file (e.g., lines 1386, 1402, 1444).
   ```suggestion
       _sendKeyUp(keysym, code) {
           if (!UI.rfb) return;
   ```



##########
systemvm/agent/noVNC/app/ui.js:
##########
@@ -1740,6 +1753,51 @@ const UI = {
         UI.idleControlbar();
     },
 
+    _sendKeyUp(keysym, code) {
+        UI.rfb.sendKey(keysym, code, false);
+    },
+
+    // Release a single modifier key if it's pressed
+    _releaseModifierKey(keyName) {
+        const keyConfig = UI._modifierKeys[keyName];
+        if (!keyConfig) return false;
+
+        const btn = document.getElementById(keyConfig.buttonId);
+        if (!btn || !btn.classList.contains("noVNC_selected")) {
+            return false;
+        }
+
+        UI._sendKeyUp(keyConfig.keysym, keyConfig.code);
+        btn.classList.remove("noVNC_selected");
+        return true;
+    },

Review Comment:
   Missing null check for `UI.rfb` before calling `_sendKeyUp()`. Although 
`_releaseAllModifierKeys()` checks for `UI.rfb` existence, this method can be 
called independently and should be defensive. Add a check like `if (!UI.rfb) 
return false;` at the beginning of the method.



##########
systemvm/agent/noVNC/app/ui.js:
##########
@@ -1740,6 +1753,51 @@ const UI = {
         UI.idleControlbar();
     },
 
+    _sendKeyUp(keysym, code) {
+        UI.rfb.sendKey(keysym, code, false);
+    },
+
+    // Release a single modifier key if it's pressed
+    _releaseModifierKey(keyName) {
+        const keyConfig = UI._modifierKeys[keyName];
+        if (!keyConfig) return false;
+
+        const btn = document.getElementById(keyConfig.buttonId);
+        if (!btn || !btn.classList.contains("noVNC_selected")) {
+            return false;
+        }
+
+        UI._sendKeyUp(keyConfig.keysym, keyConfig.code);
+        btn.classList.remove("noVNC_selected");
+        return true;
+    },
+
+    // Release all currently pressed modifier keys
+    _releaseAllModifierKeys() {
+        if (!UI.rfb || UI.rfb._rfbConnectionState !== 'connected') {
+            return false;
+        }
+
+        let keysReleased = false;
+
+        // Release all modifier keys
+        for (const keyName in UI._modifierKeys) {
+            if (UI._releaseModifierKey(keyName)) {
+                keysReleased = true;
+            }
+        }
+
+        // Also check RFB's internal shift state (it tracks this separately)
+        if (UI.rfb._shiftPressed) {
+            const shiftConfig = UI._modifierKeys.shift;
+            UI._sendKeyUp(shiftConfig.keysym, shiftConfig.code);
+            keysReleased = true;
+        }
+
+        return keysReleased;
+    },
+
+

Review Comment:
   [nitpick] Extra blank line. Remove one of the blank lines to maintain 
consistency with the rest of the codebase, which uses single blank lines 
between methods.
   ```suggestion
   
   ```



##########
systemvm/agent/noVNC/app/ui.js:
##########
@@ -1740,6 +1753,51 @@ const UI = {
         UI.idleControlbar();
     },
 
+    _sendKeyUp(keysym, code) {
+        UI.rfb.sendKey(keysym, code, false);
+    },
+
+    // Release a single modifier key if it's pressed
+    _releaseModifierKey(keyName) {
+        const keyConfig = UI._modifierKeys[keyName];
+        if (!keyConfig) return false;
+
+        const btn = document.getElementById(keyConfig.buttonId);
+        if (!btn || !btn.classList.contains("noVNC_selected")) {
+            return false;
+        }
+
+        UI._sendKeyUp(keyConfig.keysym, keyConfig.code);
+        btn.classList.remove("noVNC_selected");
+        return true;
+    },
+
+    // Release all currently pressed modifier keys
+    _releaseAllModifierKeys() {
+        if (!UI.rfb || UI.rfb._rfbConnectionState !== 'connected') {

Review Comment:
   Accessing the private property `_rfbConnectionState` directly breaks 
encapsulation. The RFB class may change this internal implementation in the 
future. Consider using a public API method to check the connection state, or 
checking if `UI.connected` is true instead, which is already used throughout 
the codebase to track connection status.
   ```suggestion
           if (!UI.connected) {
   ```



##########
systemvm/agent/noVNC/app/ui.js:
##########
@@ -1740,6 +1753,51 @@ const UI = {
         UI.idleControlbar();
     },
 
+    _sendKeyUp(keysym, code) {
+        UI.rfb.sendKey(keysym, code, false);
+    },
+
+    // Release a single modifier key if it's pressed
+    _releaseModifierKey(keyName) {
+        const keyConfig = UI._modifierKeys[keyName];
+        if (!keyConfig) return false;
+
+        const btn = document.getElementById(keyConfig.buttonId);
+        if (!btn || !btn.classList.contains("noVNC_selected")) {
+            return false;
+        }
+
+        UI._sendKeyUp(keyConfig.keysym, keyConfig.code);
+        btn.classList.remove("noVNC_selected");
+        return true;
+    },
+
+    // Release all currently pressed modifier keys
+    _releaseAllModifierKeys() {
+        if (!UI.rfb || UI.rfb._rfbConnectionState !== 'connected') {
+            return false;
+        }
+
+        let keysReleased = false;
+
+        // Release all modifier keys
+        for (const keyName in UI._modifierKeys) {
+            if (UI._releaseModifierKey(keyName)) {
+                keysReleased = true;
+            }
+        }
+
+        // Also check RFB's internal shift state (it tracks this separately)
+        if (UI.rfb._shiftPressed) {
+            const shiftConfig = UI._modifierKeys.shift;
+            UI._sendKeyUp(shiftConfig.keysym, shiftConfig.code);
+            keysReleased = true;
+        }

Review Comment:
   Accessing the private property `_shiftPressed` directly breaks 
encapsulation. This internal RFB state may not be reliable or could change in 
future versions. Additionally, there's already logic to release shift via the 
button state check above, making this additional check potentially redundant.
   ```suggestion
   
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to