[PR #1005] [CLOSED] Fix RDP tab focus issue when switching between tabs (#530) #3859

Closed
opened 2026-03-13 13:02:02 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/1Remote/1Remote/pull/1005
Author: @Copilot
Created: 10/18/2025
Status: Closed

Base: mainHead: copilot/fix-rdp-tab-focus-issue


📝 Commits (3)

  • b5dee3c Initial plan
  • 155e020 Fix RDP tab focus issue using Win32 SetForegroundWindow API
  • b5f3c5f Improve RDP focus handling with child window focus and SetFocus API

📊 Changes

1 file changed (+43 additions, -10 deletions)

View changed files

📝 Ui/View/Host/ProtocolHosts/AxMsRdpClient09Host.xaml.cs (+43 -10)

📄 Description

Problem

When switching between RDP tabs, keyboard focus remained on the previous (hidden) RDP session instead of transferring to the newly selected tab. Users had to manually click on the screen to regain proper keyboard focus, making tab switching frustrating and interrupting workflow.

This issue was reported in #530 and had been a known limitation as indicated by the comment in the code: "try to fix https://github.com/1Remote/1Remote/issues/530, but failed".

Root Cause

The RDP client is an ActiveX control (AxMsRdpClient9NotSafeForScripting) hosted in a WindowsFormsHost within WPF. The existing FocusOnMe() method attempted to use standard WPF focus methods:

this.Focus();
RdpHost.Focus();
rdp.Focus();

However, these methods don't properly handle focus transfer to a Windows Forms control's native window handle. WPF's logical focus system and Windows Forms' focus mechanism are separate, and the ActiveX control requires setting focus at the Win32 window level.

Additionally, the RDP ActiveX control creates internal child windows for rendering and input handling. Simply focusing the parent control window is insufficient - the child window that actually handles keyboard input must be focused directly.

Solution

This fix uses Win32 APIs to properly set focus to the RDP control's child window when switching tabs. The implementation finds and focuses the child rendering/input window within the RDP ActiveX control hierarchy.

Changes Made

  1. Added Win32 API Declarations:

    • SetForegroundWindow - Sets the window as the active foreground window
    • SetFocus - Sets keyboard focus to a specific window
    • GetWindow - Retrieves child windows from the control hierarchy
  2. Fixed GetHostHwnd() Method: Changed from returning IntPtr.Zero to returning the actual RDP control's window handle with proper initialization checks:

    if (_rdpClient is { IsHandleCreated: true })
    {
        return _rdpClient.Handle;
    }
    
  3. Updated FocusOnMe() Method: Now properly handles the RDP control's window hierarchy:

    • Focuses the WindowsFormsHost container
    • Focuses the RDP control itself
    • Uses GetWindow to find the child rendering/input window
    • Focuses the child window using SetFocus (with fallback to parent if no child found)
    • Calls SetForegroundWindow to activate the window

Testing

This fix requires a Windows environment for testing:

  • Create multiple RDP connections in separate tabs
  • Switch between tabs using mouse clicks on tab headers
  • Switch between tabs using keyboard shortcuts (Ctrl+1 through Ctrl+9)
  • Verify that keyboard input is immediately sent to the visible tab after switching
  • Verify that no manual click is required to activate keyboard input

Impact

  • Minimal changes: Only one file modified
  • No breaking changes: Maintains backward compatibility
  • Improved UX: Eliminates the need to click after switching tabs
  • Proper handling of ActiveX control window hierarchy
Original prompt
  1. 阅读issue #530,并阅读其中相关联的issue,充分分析问题现象。
  2. 完整阅读代码后,分析并尝试解决该issue中描述的tab页中从一个RDP切换到另一个RDP时,输入焦点依然停留在第一个RDP中的问题。

💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/1Remote/1Remote/pull/1005 **Author:** [@Copilot](https://github.com/apps/copilot-swe-agent) **Created:** 10/18/2025 **Status:** ❌ Closed **Base:** `main` ← **Head:** `copilot/fix-rdp-tab-focus-issue` --- ### 📝 Commits (3) - [`b5dee3c`](https://github.com/1Remote/1Remote/commit/b5dee3cf99946d6a7bf788909bc63bdfd46c4b95) Initial plan - [`155e020`](https://github.com/1Remote/1Remote/commit/155e02003f1ef75098bd3b143803398fa8012012) Fix RDP tab focus issue using Win32 SetForegroundWindow API - [`b5f3c5f`](https://github.com/1Remote/1Remote/commit/b5f3c5f73ee12b6038d281e3ecad8c308492b580) Improve RDP focus handling with child window focus and SetFocus API ### 📊 Changes **1 file changed** (+43 additions, -10 deletions) <details> <summary>View changed files</summary> 📝 `Ui/View/Host/ProtocolHosts/AxMsRdpClient09Host.xaml.cs` (+43 -10) </details> ### 📄 Description ## Problem When switching between RDP tabs, keyboard focus remained on the previous (hidden) RDP session instead of transferring to the newly selected tab. Users had to manually click on the screen to regain proper keyboard focus, making tab switching frustrating and interrupting workflow. This issue was reported in #530 and had been a known limitation as indicated by the comment in the code: "try to fix https://github.com/1Remote/1Remote/issues/530, but failed". ## Root Cause The RDP client is an ActiveX control (`AxMsRdpClient9NotSafeForScripting`) hosted in a `WindowsFormsHost` within WPF. The existing `FocusOnMe()` method attempted to use standard WPF focus methods: ```csharp this.Focus(); RdpHost.Focus(); rdp.Focus(); ``` However, these methods don't properly handle focus transfer to a Windows Forms control's native window handle. WPF's logical focus system and Windows Forms' focus mechanism are separate, and the ActiveX control requires setting focus at the Win32 window level. Additionally, the RDP ActiveX control creates internal child windows for rendering and input handling. Simply focusing the parent control window is insufficient - the child window that actually handles keyboard input must be focused directly. ## Solution This fix uses Win32 APIs to properly set focus to the RDP control's child window when switching tabs. The implementation finds and focuses the child rendering/input window within the RDP ActiveX control hierarchy. ### Changes Made 1. **Added Win32 API Declarations**: - `SetForegroundWindow` - Sets the window as the active foreground window - `SetFocus` - Sets keyboard focus to a specific window - `GetWindow` - Retrieves child windows from the control hierarchy 2. **Fixed `GetHostHwnd()` Method**: Changed from returning `IntPtr.Zero` to returning the actual RDP control's window handle with proper initialization checks: ```csharp if (_rdpClient is { IsHandleCreated: true }) { return _rdpClient.Handle; } ``` 3. **Updated `FocusOnMe()` Method**: Now properly handles the RDP control's window hierarchy: - Focuses the `WindowsFormsHost` container - Focuses the RDP control itself - Uses `GetWindow` to find the child rendering/input window - Focuses the child window using `SetFocus` (with fallback to parent if no child found) - Calls `SetForegroundWindow` to activate the window ## Testing This fix requires a Windows environment for testing: - Create multiple RDP connections in separate tabs - Switch between tabs using mouse clicks on tab headers - Switch between tabs using keyboard shortcuts (Ctrl+1 through Ctrl+9) - Verify that keyboard input is immediately sent to the visible tab after switching - Verify that no manual click is required to activate keyboard input ## Impact - Minimal changes: Only one file modified - No breaking changes: Maintains backward compatibility - Improved UX: Eliminates the need to click after switching tabs - Proper handling of ActiveX control window hierarchy <!-- START COPILOT CODING AGENT SUFFIX --> <details> <summary>Original prompt</summary> > 1. 阅读issue #530,并阅读其中相关联的issue,充分分析问题现象。 > 2. 完整阅读代码后,分析并尝试解决该issue中描述的tab页中从一个RDP切换到另一个RDP时,输入焦点依然停留在第一个RDP中的问题。 </details> <!-- START COPILOT CODING AGENT TIPS --> --- 💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click [here](https://survey3.medallia.com/?EAHeSx-AP01bZqG0Ld9QLQ) to start the survey. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-03-13 13:02:02 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/1Remote#3859
No description provided.