[GH-ISSUE #530] Changing RDP tabs should focus the new tab #1392

Closed
opened 2026-02-28 12:04:11 +03:00 by kerem · 12 comments
Owner

Originally created by @OronDF343 on GitHub (Oct 16, 2023).
Original GitHub issue: https://github.com/1Remote/1Remote/issues/530

Originally assigned to: @VShawn on GitHub.

When I am working on an RDP session and I change tabs, for some reason keyboard focus is retained by the previous tab. Whatever I type is affecting the other (hidden) tab until I click on the screen.

Changing tabs should always immediately focus the keyboard on the displayed session.

Originally created by @OronDF343 on GitHub (Oct 16, 2023). Original GitHub issue: https://github.com/1Remote/1Remote/issues/530 Originally assigned to: @VShawn on GitHub. When I am working on an RDP session and I change tabs, for some reason keyboard focus is retained by the previous tab. Whatever I type is affecting the other (hidden) tab until I click on the screen. Changing tabs should always immediately focus the keyboard on the displayed session.
Author
Owner

@VShawn commented on GitHub (Oct 16, 2023):

thankx for your remind, This is the first time I'm aware of this bug, but don't worry, it will be fixed soon.

<!-- gh-comment-id:1764379178 --> @VShawn commented on GitHub (Oct 16, 2023): thankx for your remind, This is the first time I'm aware of this bug, but don't worry, it will be fixed soon.
Author
Owner

@VShawn commented on GitHub (Oct 17, 2023):

After a day of test, I discovered that I couldn't fix this problem quickly. I couldn't find a way through the code to cancel the focus of the previous RDP session and focus on the new RDP.

<!-- gh-comment-id:1766206226 --> @VShawn commented on GitHub (Oct 17, 2023): After a day of test, I discovered that I couldn't fix this problem quickly. I couldn't find a way through the code to cancel the focus of the previous RDP session and focus on the new RDP.
Author
Owner

@itagagaki commented on GitHub (Dec 21, 2025):

I think this is a Drabablz issue rather than an issue with the RDP session.

<!-- gh-comment-id:3678686030 --> @itagagaki commented on GitHub (Dec 21, 2025): I think this is a Drabablz issue rather than an issue with the RDP session.
Author
Owner

@itagagaki commented on GitHub (Dec 21, 2025):

My investigation revealed the following:

  1. Open two RDP hosts (Windows) in two tabs in a single window.
  2. Click on the desktop of the hosts. Then type the Tab key. This operation brings the Windows Start button into focus. Do this on each host.
  3. Switch the tab of window.
  4. Try to type the Tab key five times.

Nothing happens until the fourth attempt, after which the focus shifts. This is odd.
The cause is unknown, but this behavior could provide a clue.

<!-- gh-comment-id:3678818279 --> @itagagaki commented on GitHub (Dec 21, 2025): My investigation revealed the following: 1. Open two RDP hosts (Windows) in two tabs in a single window. 2. Click on the desktop of the hosts. Then type the Tab key. This operation brings the Windows Start button into focus. Do this on each host. 3. Switch the tab of window. 4. Try to type the Tab key five times. Nothing happens until the fourth attempt, after which the focus shifts. This is odd. The cause is unknown, but this behavior could provide a clue.
Author
Owner

@itagagaki commented on GitHub (Dec 22, 2025):

I used a tool to observe the keyboard events that were actually being received by the remote Windows system.
https://kts.sakaiweb.com/keymill.html
(Maybe Japanese only)

Then, various strange phenomena were observed.

For example, opening or closing an entirely completely unrelated application on the client-side Windows caused Keymill to react on the remote Windows machine. It's utterly bizarre.

This strange behaviour may have caused some of the unexplained bug reports.

<!-- gh-comment-id:3681813281 --> @itagagaki commented on GitHub (Dec 22, 2025): I used a tool to observe the keyboard events that were actually being received by the remote Windows system. https://kts.sakaiweb.com/keymill.html (Maybe Japanese only) Then, various strange phenomena were observed. For example, opening or closing an entirely completely unrelated application on the client-side Windows caused Keymill to react on the remote Windows machine. It's utterly bizarre. This strange behaviour may have caused some of the unexplained bug reports.
Author
Owner

@VShawn commented on GitHub (Dec 23, 2025):

I also suspected it might be an issue with Drabablz, but so far I haven't found any other suitable tab controls support splitting, so I haven't proceeded with replacement testing.

Additionally, calling rdp.focus(); does not shift the focus to rdp, which I believe is also problematic.

<!-- gh-comment-id:3684916810 --> @VShawn commented on GitHub (Dec 23, 2025): I also suspected it might be an issue with Drabablz, but so far I haven't found any other suitable tab controls support splitting, so I haven't proceeded with replacement testing. Additionally, calling `rdp.focus();` does not shift the focus to rdp, which I believe is also problematic.
Author
Owner

@itagagaki commented on GitHub (Dec 28, 2025):

As part of my investigation, I decided to observe the m.Msg in AxMsRdpClient9NotSafeForScriptingEx.WndProc(ref System.Windows.Forms.Message m).

--

When switching between two open RDP windows in separated, the following messages were received by AxMsRdpClient9NotSafeForScriptingEx.WndProc() in sequence:

0x0119 (?) wParam=1
0x0007 (WM_SETFOCUS)
0x0008 (WM_KILLFOCUS)
0x0119 (?) wParam=0

For the WM_SETFOCUS, the wParam parameter appears to be the handle of the first child window of the Dragablz window.

(In rare cases, however, it is the handle of the Dragablez window itself rather than that of a child window. I think this is just another glitch.)

--

When both RDP tabs were within the same Dragablz window, switching to the first tab caused AxMsRdpClient9NotSafeForScriptingEx.WndProc() to receive the following messages in order:

0x000A (WM_ENABLE) wParam=1
0x001F (WM_CANCELMODE)
0x000A (WM_ENABLE) wParam=0
0x000E (WM_GETTEXTLENGTH)
0x000D (WM_GETTEXT).

When switching to the second tab:

0x001F (WM_CANCELMODE)
0x000A (WM_ENABLE) wParam=0
0x000A (WM_ENABLE) wParam=1
0x000E (WM_GETTEXTLENGTH)
0x000D (WM_GETTEXT).

WM_GETTEXTLENGTH and WM_GETTEXT are probably caused by the processing of the change to the window title, and are unrelated to this issue.

WM_CANCELMODE and WM_ENABLE are sent by child.IsEnabled = isSelected; in Dragblz.TabablzControl.UpdasteSelectedItem().

If isSelected is false, then WM_CANCELMODE is sent before WM_ENABLE with wParam=0.
If isSelected is true, then WM_ENABLE is sent with wParam=1.

In any case, WM_SETFOCUS is not being received.
Despite exhausting all possibilities with AxMsRdpClient09Host.FocusOnMe().

<!-- gh-comment-id:3694835487 --> @itagagaki commented on GitHub (Dec 28, 2025): As part of my investigation, I decided to observe the `m.Msg` in `AxMsRdpClient9NotSafeForScriptingEx.WndProc(ref System.Windows.Forms.Message m)`. -- When switching between two open RDP windows in separated, the following messages were received by `AxMsRdpClient9NotSafeForScriptingEx.WndProc()` in sequence: 0x0119 (?) `wParam`=1 0x0007 (`WM_SETFOCUS`) 0x0008 (`WM_KILLFOCUS`) 0x0119 (?) `wParam`=0 For the `WM_SETFOCUS`, the `wParam` parameter appears to be the handle of the first child window of the Dragablz window. (In rare cases, however, it is the handle of the Dragablez window itself rather than that of a child window. I think this is just another glitch.) -- When both RDP tabs were within the same Dragablz window, switching to the first tab caused `AxMsRdpClient9NotSafeForScriptingEx.WndProc()` to receive the following messages in order: 0x000A (`WM_ENABLE`) `wParam`=1 0x001F (`WM_CANCELMODE`) 0x000A (`WM_ENABLE`) `wParam`=0 0x000E (`WM_GETTEXTLENGTH`) 0x000D (`WM_GETTEXT`). When switching to the second tab: 0x001F (`WM_CANCELMODE`) 0x000A (`WM_ENABLE`) `wParam`=0 0x000A (`WM_ENABLE`) `wParam`=1 0x000E (`WM_GETTEXTLENGTH`) 0x000D (`WM_GETTEXT`). `WM_GETTEXTLENGTH` and `WM_GETTEXT` are probably caused by the processing of the change to the window title, and are unrelated to this issue. `WM_CANCELMODE` and `WM_ENABLE` are sent by `child.IsEnabled = isSelected;` in `Dragblz.TabablzControl.UpdasteSelectedItem()`. If `isSelected` is false, then `WM_CANCELMODE` is sent before `WM_ENABLE` with `wParam`=0. If `isSelected` is true, then `WM_ENABLE` is sent with `wParam`=1. In any case, `WM_SETFOCUS` is not being received. Despite exhausting all possibilities with `AxMsRdpClient09Host.FocusOnMe()`.
Author
Owner

@VShawn commented on GitHub (Dec 29, 2025):

Then does it mean we can send WM_SETFOCUS to rdp object after a tab switching as a workaround?


BTW As I am an amateur UI software developer and not very familiar with windows message handles. May I ask how to observe the m.Msg in AxMsRdpClient9NotSafeForScriptingEx.WndProc(ref System.Windows.Forms.Message m).?

<!-- gh-comment-id:3695592439 --> @VShawn commented on GitHub (Dec 29, 2025): Then does it mean we can send WM_SETFOCUS to rdp object after a tab switching as a workaround? --- BTW As I am an amateur UI software developer and not very familiar with windows message handles. May I ask how to `observe the m.Msg in AxMsRdpClient9NotSafeForScriptingEx.WndProc(ref System.Windows.Forms.Message m).`?
Author
Owner

@itagagaki commented on GitHub (Dec 29, 2025):

Then does it mean we can send WM_SETFOCUS to rdp object after a tab switching as a workaround?

Yeah, I did think so too, and tried that, but no luck so far.

How to observe the m.Msg:

I just used a simple way :-)

    internal class AxMsRdpClient9NotSafeForScriptingEx : AxMSTSCLib.AxMsRdpClient9NotSafeForScripting
    {
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            SimpleLogHelper.DebugInfo($"Message {m.Msg:X} wParam {m.WParam:X} lParam {m.LParam:X} HWnd {m.HWnd} this.Handle {this.Handle:X}");

Of course, this merely observes messages sent to this window.
I think there's a chance that Win32 or Dragblz is sending WM_SETFOCUS to other targets when the tab is switched.
If there was a tool that could capture all the window messages flying around on the OS, we could probably figure that out. I reckon there's probably a tool like that out there, so I'm thinking of having a look for it.

I use this tool to view info about all windows. This lets me figure out which window m.HWnd is referring to.
GUIPropView - View and set Windows properties from command line or GUI

<!-- gh-comment-id:3696363315 --> @itagagaki commented on GitHub (Dec 29, 2025): > Then does it mean we can send WM_SETFOCUS to rdp object after a tab switching as a workaround? Yeah, I did think so too, and tried that, but no luck so far. #### How to observe the `m.Msg`: I just used a simple way :-) ``` internal class AxMsRdpClient9NotSafeForScriptingEx : AxMSTSCLib.AxMsRdpClient9NotSafeForScripting { protected override void WndProc(ref System.Windows.Forms.Message m) { SimpleLogHelper.DebugInfo($"Message {m.Msg:X} wParam {m.WParam:X} lParam {m.LParam:X} HWnd {m.HWnd} this.Handle {this.Handle:X}"); ``` Of course, this merely observes messages sent to this window. I think there's a chance that Win32 or Dragblz is sending WM_SETFOCUS to other targets when the tab is switched. If there was a tool that could capture all the window messages flying around on the OS, we could probably figure that out. I reckon there's probably a tool like that out there, so I'm thinking of having a look for it. I use this tool to view info about all windows. This lets me figure out which window m.HWnd is referring to. [GUIPropView - View and set Windows properties from command line or GUI](https://www.nirsoft.net/utils/gui_prop_view.html)
Author
Owner

@itagagaki commented on GitHub (Jan 1, 2026):

I've found this and am using it for my investigation, but I haven't gained anything from it yet.
API Monitor: Spy on API Calls and COM Interfaces (Freeware 32-bit and 64-bit Versions!) | rohitab.com

<!-- gh-comment-id:3703293850 --> @itagagaki commented on GitHub (Jan 1, 2026): I've found this and am using it for my investigation, but I haven't gained anything from it yet. [API Monitor: Spy on API Calls and COM Interfaces (Freeware 32-bit and 64-bit Versions!) | rohitab.com](http://www.rohitab.com/apimonitor)
Author
Owner

@itagagaki commented on GitHub (Jan 1, 2026):

The investigation is still ongoing, but I've learned something.

When the mouse button is pressed on a tab, Dragablz reacts and the following sequence of calls proceeds:

DragablzItem.ThumbOnDragStarted()
DragablzItem.OnDragStarted()
TabablzControl.ItemDragStarted()

Then, SelectedItem = item; statement in ItemDragStarted() triggers the setter for _1RM.View.Host.TabWindowViewModel.SelectedItem.

In the current 1Remote implementation, it attempts to gain focus with _selectedItem.Content.FocusOnMe(); within this setter. However, this is too early. Because the tab switching process by Dragablz is still halfway through at this point.

<!-- gh-comment-id:3703755694 --> @itagagaki commented on GitHub (Jan 1, 2026): The investigation is still ongoing, but I've learned something. When the mouse button is pressed on a tab, Dragablz reacts and the following sequence of calls proceeds: DragablzItem.ThumbOnDragStarted() DragablzItem.OnDragStarted() TabablzControl.ItemDragStarted() Then, `SelectedItem = item;` statement in ItemDragStarted() triggers the setter for `_1RM.View.Host.TabWindowViewModel.SelectedItem`. In the current 1Remote implementation, it attempts to gain focus with `_selectedItem.Content.FocusOnMe();` within this setter. However, this is too early. Because the tab switching process by Dragablz is still halfway through at this point.
Author
Owner

@itagagaki commented on GitHub (Jan 1, 2026):

Switching tabs also changes the window title of one of the child windows in the Dragablz window to the new title given to the Dragablz window itself via the SelectedItem property setter of the _1RM.View.Host.TabWindowViewModel. Presumably, the switch is fully complete at this stage.

However, it does not seem that Dragablz provides an event to notify this change. It also appears that Dragablz itself cannot determine the exact timing of this change.

Therefore, I am considering the following approach:

  1. Start a periodic timer event when SelectedItem changes
  2. In the event handler, find the child window within the parent Tabablz window that has the same title as the one given to the parent window
  3. When found, set the focus and discard the periodic timer event
<!-- gh-comment-id:3703862244 --> @itagagaki commented on GitHub (Jan 1, 2026): Switching tabs also changes the window title of one of the child windows in the Dragablz window to the new title given to the Dragablz window itself via the `SelectedItem` property setter of the `_1RM.View.Host.TabWindowViewModel`. Presumably, the switch is fully complete at this stage. However, it does not seem that Dragablz provides an event to notify this change. It also appears that Dragablz itself cannot determine the exact timing of this change. Therefore, I am considering the following approach: 1. Start a periodic timer event when `SelectedItem` changes 2. In the event handler, find the child window within the parent Tabablz window that has the same title as the one given to the parent window 3. When found, set the focus and discard the periodic timer event
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#1392
No description provided.