71

I have 3 virtual desktops in Windows 10.
On one of those desktop I run mstsc fullscreen.

To switch desktop I can use windows+ctrl+left or right.
But when I am in a fullscreen mstsc this key is captured by mstsc and switching doesn't work.
Is there a way to change this behaviour?

2
  • 1
    I need an answer on this too!
    – Antony
    Commented Mar 9, 2016 at 16:10
  • 1
    Upvoting, because this would be great. It would be nice to choose which Windows key combinations apply to RDP or computer
    – MikeMurko
    Commented Aug 29, 2016 at 17:50

11 Answers 11

93

I was looking for a solution to this problem and just found one !

CTRL + ALT + HOME gives keyboard focus back to host when in Remote Desktop.
Then you can do WIN + CTRL + LEFT or RIGHT to switch between virtual desktops.
Not ideal, but i'll probably have autohotkey deal with these 2 shortcuts.

4
  • 5
    That's so f*** brilliant!! I was looking for something like this for awhile and the best I found was Ctrl + alt + break(pause), which closes the full screen mode - it's very uncomfortable! I'd give you bounty if this was stackoverflow, but I can't do this here. Thanks +1! Commented Jan 18, 2018 at 13:23
  • 2
    Lov ya so much, take my uppoints!!
    – Fedaykin
    Commented Jul 24, 2018 at 17:05
  • Also can confirm this works in the Mac client too. If you're RDPed into a Windows 10 machine from Mac with RDP, use Cmd+Ctrl+Left/Right Commented May 13, 2020 at 21:32
  • This deserves +1000 upvotes at least! Works wonders with a single local desktop too, if you just want to Alt+Tab out of a remote desktop when you don't set Alt+Tab to only work for “this computer” in RDP settings. This way you can Alt+Tab between remote apps, and pressing Ctrl+Alt+Home allows you to Alt+Tab back to the local desktop! Commented May 25, 2020 at 7:20
19

It turns out that in remote desktop client, you should select "Only this computer" when it comes to applying Windows Key Combination.

Remote Desktop Local Resources

3
  • 9
    That works, but now I can't use ALT+TAB
    – roeland
    Commented Mar 14, 2016 at 9:51
  • 3
    I also have the same problem. I wish there was a way to make it ignore just win+ctrl+left/right
    – Ege Özcan
    Commented Oct 6, 2016 at 15:31
  • 2
    @EgeÖzcan there is (sort of)! See this answer
    – Luke
    Commented May 5, 2017 at 16:16
10

If you have a touchpad, you can try the four finger gesture.

From Microsoft Support - Touchpad gestures for Windows 10

Switch virtual desktops: Place four fingers on the touchpad and swipe right or left.

I am working with two virtual desktops in Windows 10. On one of those desktop I am accessing a Win 7 through Remote Desktop in full screen mode.

I can switch between the two virtual desktops with this single gesture. It works for me.

2
  • doesnt work in full screen mode Commented May 13, 2020 at 5:41
  • 2
    @NishantLakhara - it does work in full screen mode, at least in my hands....
    – malcook
    Commented Nov 17, 2020 at 19:46
9

First, I wanted the Windows keys to work on the remote computer (Alt-Tab for instance), so I have "Only when using the full screen" for the "Apply Windows key combinaisons" setting.

Then, since very few key combinaisons are able to get you out of the remote desktop when it is full screen, you have to use CTRL-ALT-HOME, which brings the connection bar, but also gives back the control to the local computer.

So I wrote this autohotkey script : switchVirtualDesktopWithRD.ahk. It is completely based on this script, so I take no credit. I simply modified it for my needs. You can ajust it to yours...

In my case, I only have two virtual desktops : the first is the main one, and the second is where I run a full screen remote desktop client.

What the script does when I press CTRL-ALT-HOME :

  • If I am on the second virtual desktop, the one where I run a full screen remote desktop client, that first shows the connection bar. I then press the HOME key again (with CTRL and ALT still pressed) and I'm back to the first, main desktop. If there is no full screen session going on on the second desktop, the first combinaison immediatly switch to the first desktop.

  • If I am on the first desktop, it switches to the second one immediatly.

In other words, I always use CTRL-ALT-HOME to switch between desktops.

2
  • I like this. If we run an ahk script on the remote computer(s) (and set them to start when you login), I wonder if we could translate a CTRL-WIN-LEFT to CTRL-ALT-HOME and trigger the focus switch to the RDP connection bar from the remote ahk. Then you just need to press CTRL-WIN-LEFT twice to have it switch desktops.
    – Luke
    Commented Apr 27, 2017 at 18:23
  • I got it working, but with a script running only on the local machine - no need for ahk on the remote :D
    – Luke
    Commented May 5, 2017 at 16:10
7

Building off electrotype's answer I have an AHK script that will enable Ctrl+Win+Left and Ctrl+Win+Right hotkeys to switch desktops on the local computer, from within a full screen RDP session, without sacrificing any other keys within the RDP session - i.e. Alt+Tab and similar all still work as normal within the RDP session.

As we want the regular shortcut key to work on the remote computer, you must have "Only when using the full screen" for the "Apply Windows key combinaitons" setting when starting the RDP session.

I actually based my script off another script I found on the AHK forums.

What it does:

  • Run the script on your local machine (not on the remote desktop). I pasted mine into C:\users\<user>\documents\AutoHotkey.ahk so it runs when i start ahk with no arguments.
  • If you are inside an RDP session and press Ctrl+Win+(Left or right) the script first sends Ctrl+Alt+Home to focus the RDP title bar then sends the switch desktop key combo to actually switch the desktop.

Note: it gets a little buggy when using two or more virtual-remote desktops (eg. one local virtual desktop, two virtual desktops with a fullscreen RDP window on each) but I don't have time to work on it any more right now. The issue is when you switch from one virtual-remote desktop to another, you have to unbind and rebind the hot key and it's having trouble detecting this (though it shouldn't - the RDP title bar has a different window class but it doesn't always pick this up).

Ahk script:

;setTimer, windowwatch, 500
#persistent
#usehook
SLEEP_VAL := 500
DEBUG := false
keys_bound := false

while true {
    ;Debug("Waiting")
    sleep, SLEEP_VAL
    keys_bound := WaitBind()
}

WaitBind() {
    WinWaitActive, ahk_class TscShellContainerClass
    Debug("bind")
    hotkey LWin & Left, ctrl_win_left_key, on
    hotkey LWin & Right, ctrl_win_right_key, on
    return true
}

WaitUnbind() {
    WinWaitNotActive, ahk_class TscShellContainerClass
    Debug("unbind")
    hotkey LWin & Left, ctrl_win_left_key, off
    hotkey LWin & Right, ctrl_win_right_key, off
    return false
}

Debug(msg) {
    global DEBUG
    if (DEBUG) {
        tooltip %msg%
        settimer, TooltipClear, 2000
    }
}
return

z_key:
    ; simple script for testing - change the z to 'he'
    send, he
    Debug("done z")
return

j_key:
    ; testing if we can activate the RDP title bar
    send {Ctrl down}{Alt down}{Home}{Alt up}{Ctrl up}
    Debug("done j")
Return

ctrl_win_left_key:
    ; we are intercepting all Win+Left combinations so we have to do Win+Shift+Left and Win+Left manually to preserve them inside the RDP
    GetKeyState, shiftState, Shift
    GetKeyState, ctrlState, Ctrl
    if (shiftState = "D") {
        ; by default in windows Ctrl+Shift+Win+Left will act like Shift+Win+Left - shift takes precedence
        Debug("done shift win left")
        send {Shift down}{LWin down}{Left}{LWin up}{Shift up}
    } else if (ctrlState = "D") {
        Debug("done ctrl win left")
        ; the magic happens here
        send {Ctrl down}{Alt down}{Home}{Alt up}{Ctrl up}
        keys_bound := WaitUnbind()
        ;Sleep, SLEEP_VAL ;give the OS time to focus on the title bar
        send {Ctrl down}{LWin down}{Left}{LWin up}{Ctrl up}
    } else {
        Debug("done win left")
        send {LWin down}{Left}{LWin up}
    }
Return

ctrl_win_right_key:
    ; we are intercepting all Win+Right combinations so we have to do Win+Shift+Right and Win+Right manually to preserve them inside the RDP
    GetKeyState, shiftState, Shift
    GetKeyState, ctrlState, Ctrl
    if (shiftState = "D") {
        ; by default in windows Ctrl+Shift+Win+Left will act like Shift+Win+Left - shift takes precedence
        Debug("done shift win right")
        send {Shift down}{LWin down}{Right}{LWin up}{Shift up}
    } else if (ctrlState = "D") {
        Debug("done ctrl win right")
        ; the magic happens here
        send {Ctrl down}{Alt down}{Home}{Alt up}{Ctrl up}
        keys_bound := WaitUnbind()
        ;Sleep, SLEEP_VAL ;give the OS time to focus on the title bar
        send {Ctrl down}{LWin down}{Right}{LWin up}{Ctrl up}
    } else {
        Debug("done win right")
        send {LWin down}{Right}{LWin up}
    }
Return


TooltipClear:
    ; just a routine to turn off tooltip after x milliseconds
    tooltip
    settimer, TooltipClear, off
Return

windowwatch:
    ifwinactive ahk_class TscShellContainerClass
    {
      Debug("bind")
      hotkey LWin & Left, ctrl_win_left_key, on
      hotkey LWin & Right, ctrl_win_right_key, on
    }
    else
    {
     Debug("unbind")
     hotkey LWin & Left, ctrl_win_left_key, off
     hotkey LWin & Right, ctrl_win_right_key, off
    }
Return
2
  • Sometimes it feels like it's not working - I find i have to release and re-press the Ctrl+Win keys sometimes when i go from a local desktop to a remote or vice versa. Try that if it's not working, or increase the SLEEP_VAL at the top of the script to increase the delay between sending Ctrl+Alt+Home and Ctrl+Win+Left
    – Luke
    Commented May 5, 2017 at 16:20
  • This isn't working for me. It's been almost 6 years, so I'm sure things have changed. But running this on my local machine and using Ctrl+Win+Arrow in a full screen remote session does nothing as far as I can tell. Unfortunately I'm not versed enough in advanced AHK to troubleshoot this.
    – mmseng
    Commented Jan 16, 2023 at 21:25
2

I am using the script by @user16659 here: How to fix AHK to send keys to RDP fullscreen?. Plus my hotkeys to send Ctrl + Alt + Home then Ctrl + Win + Left. Works well! I found on one system I could avoid using the sleep between sending the hotkeys, but on the other I needed the 200 millisecond pause.

SetTimer, waitforrdp, -250
return

; Task View Switch Desktops Ctrl + Alt + Arrow keys
^!Left::
Send {Ctrl down}{Alt down}{Home}{Alt up}{Ctrl up}
Sleep 200
Send {Ctrl down}{LWin down}{Left}{LWin up}{Ctrl up}
return

^!Right::
Send {Ctrl down}{LWin down}{Right}{LWin up}{Ctrl up}
return

waitforrdp:
IfWinActive, ahk_class TscShellContainerClass
{
    WinWaitNotActive, ahk_class TscShellContainerClass,,3600
}
WinWaitActive, ahk_class TscShellContainerClass,,3600
Reload
return

EDIT: After using this script for a day I have found the Ctrl key gets stuck on after I have switched to my RDP window. I have read quite a few other posts about the Ctrl key getting stuck on. I have tried many of the suggestions and none of them work. I think this case of switching to a full screen RDP session might be a bit different.

1

electrotype's answer did technically work for me, however I have two qualms with it.

  1. It's based on a script/API/library which is intended for a much wider set of use cases, and as such, it's extreme overkill for this particular case.

  2. It requires you to use a different keystroke (Ctrl+Alt+Home), rather than just Ctrl+Win+arrow, or any other less annoying hotkey.

It took a while, but after a lot of close examination (I'm not an AHK expert), I was able to reverse engineer the behavior out of the heavily-abstracted script. For the purposes of this question, the entire 672 lines can effectively be replaced with only 4:

Hotkey, ^!Home, goToLeftVirtualDesktop

goToLeftVirtualDesktop:
Send {Ctrl down}{LWin down}{Left}{LWin up}{Ctrl up}
Return

The only functional difference is that the original script hooks into the Windows virtual desktop framework in order to determine which local virtual desktop (VD) you are currently on (in electrotype's and my case, that's either VD 1 or VD 2). So when you're in a full-screen Remote Desktop (RD) session, pressing Ctrl+Alt+Home first brings up the RD title bar (that's just default RD behavior, and forces RD to release control of your inputs), and pressing Ctrl+Alt+Home again triggers AHK (now that the local system has focus) to Send either Ctrl+Win+ or Ctrl+Win+, depending on which desktop you're on.

If, as in my case, you always keep your full-screen remote session on VD 2, then the above 4 lines will accomplish the same thing, except that you no longer have the option of using Ctrl+Alt+Home to switch back from VD 1 to VD 2. But you can just use Ctrl+Win+ to do that normally. Using the same (wrong) keystroke to go from VD 1 to VD 2 is not worth the extra 668 lines of code IMO.

So that solves qualm #1.

Unfortunately qualm #2 is more complicated, and even the over-engineered script from electrotype's answer doesn't (and can't) solve it. The problem is that the RD session seems to capture all key combinations until such time as you have used Ctrl+Alt+Home to escape out of the RD session, so that key combo must be pressed first. That is of course unless you change the RD "Apply Windows key combinations" setting to "On this computer", but one of the core premises of this question (for most of us here), is how to achieve the desired result without changing this setting, since doing so breaks functionality such as Alt+Tab in the RD session.

I've seen some other questions/answers suggesting it's possible via different complicated scripting mechanisms, or combinations of local plus remote AHK scripts, but those are outside the scope of this answer. I hope to find one that works at some point.

At any rate, if you just wanted the functionality of Ctrl+Alt+Home (twice) to switch your desktop, away from a full-screen RD session, in a much more understandable script, then here's your answer. Since it's only 4 lines, it's at least much easier to customize which VD you want to switch to.

P.S. As an aside, I will also just note that, in my quest to make Ctrl+Win+arrow capturable out of a full-screen RD session I came across many posts claiming that reloading or suspending and un-suspending the AHK script after the RD session is full-screened will allow defined Hotkeys to function, even when the full-screen RD session has focus. However I tried countless variations on this theme and could not get any response from AHK whatsoever, until Ctrl+Alt+Home was pressed. My assumption is that these claims are either outdated and do not apply to the latest RD application, or they were simply working with RD's "Apply Windows key combinations" setting set to "On this computer". Additionally, some of them were using 3rd party RD applications, which presumably handle input capture differently.

Update: I did eventually get the following script to sometimes activate the full-screen RD session titlebar:

#NoEnv
#SingleInstance force
#UseHook
#Persistent
SendMode Input
Active := false
SetTimer RDPActive, 500
Return

RDPActive:
    if WinActive("ahk_class TscShellContainerClass") {
        if(!Active) {
            Active := true
            SoundBeep 1500
            Suspend off
            Hotkey F2, Pressed, on
        }
    }
    else {
        if(Active) {
            Active := false
            SoundBeep 1000
            Suspend on
        }
    }
    Return

Pressed:
    SoundBeep 2000
    Send {LCtrl down}{LAlt down}{Home}{LAlt up}{LCtrl up}
    ;Sleep 500
    ;Send {LCtrl down}{LWin down}{Left}{LWin up}{LCtrl up}
    Return

However it's incredibly inconsistent, and I haven't figured out why. Even if it worked 100% of the time, it uses F2 as the Hotkey, and I've not been able to get Ctrl+Win+arrow to be recognized in the RD session at all.

0

A simple workaround without a script is to use some kind of Windows accessibility tool that always stays on top of other windows (like Live Captions or Clock StopWatch), or tools like PowerToys to place a window "ALWAYS ON TOP".

Then you just click on this window from the full screen remote desktop and use WIN+CTRL+(LEFT/RIGHT) or WIN+TAB to switch between the virtual desktop (maybe binded to your mouse button so you could do everything with the mouse without the keyboard).

0

It seems that when RDP is in full-screen mode, AutoHotkey does not capture the WIN+CTRL+RIGHT/LEFT hotkeys, so any solution involving these hotkeys won't work.

I've searched for key combinations that RDP doesn't capture (and which are comfortable to use), so I've come up with ALT+CapsLock.

Then, I created a simple AutoHotkey script that capture ALT+CapsLock and uses this helper DLL to switch between desktops via API instead of sending hotkeys (I think it's more reliable). https://github.com/Ciantic/VirtualDesktopAccessor

Basically, I copied some code from the project's V2 example and add the ALT+CapsLock handling.

This is my script:

; https://github.com/Ciantic/VirtualDesktopAccessor
SetWorkingDir(A_ScriptDir)

; Path to the DLL, relative to the script
VDA_PATH := A_ScriptDir . "\VirtualDesktopAccessor.dll"
hVirtualDesktopAccessor := DllCall("LoadLibrary", "Str", VDA_PATH, "Ptr")

GetDesktopCountProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GetDesktopCount", "Ptr")
GoToDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GoToDesktopNumber", "Ptr")
GetCurrentDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GetCurrentDesktopNumber", "Ptr")
IsWindowOnCurrentVirtualDesktopProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "IsWindowOnCurrentVirtualDesktop", "Ptr")
IsWindowOnDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "IsWindowOnDesktopNumber", "Ptr")
MoveWindowToDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "MoveWindowToDesktopNumber", "Ptr")
IsPinnedWindowProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "IsPinnedWindow", "Ptr")
GetDesktopNameProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GetDesktopName", "Ptr")
SetDesktopNameProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "SetDesktopName", "Ptr")
CreateDesktopProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "CreateDesktop", "Ptr")
RemoveDesktopProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "RemoveDesktop", "Ptr")

; On change listeners
RegisterPostMessageHookProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "RegisterPostMessageHook", "Ptr")
UnregisterPostMessageHookProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "UnregisterPostMessageHook", "Ptr")

GetDesktopCount() {
    global GetDesktopCountProc
    count := DllCall(GetDesktopCountProc, "Int")
    return count
}
MoveCurrentWindowToDesktop(number) {
    global MoveWindowToDesktopNumberProc, GoToDesktopNumberProc
    activeHwnd := WinGetID("A")
    DllCall(MoveWindowToDesktopNumberProc, "Ptr", activeHwnd, "Int", number, "Int")
    DllCall(GoToDesktopNumberProc, "Int", number, "Int")
}
GoToPrevDesktop() {
    global GetCurrentDesktopNumberProc, GoToDesktopNumberProc
    current := DllCall(GetCurrentDesktopNumberProc, "Int")
    last_desktop := GetDesktopCount() - 1
    ; If current desktop is 0, go to last desktop
    if (current = 0) {
        MoveOrGotoDesktopNumber(last_desktop)
    } else {
        MoveOrGotoDesktopNumber(current - 1)
    }
    return
}

GoToNextDesktop() {
    global GetCurrentDesktopNumberProc, GoToDesktopNumberProc
    current := DllCall(GetCurrentDesktopNumberProc, "Int")
    last_desktop := GetDesktopCount() - 1
    ; If current desktop is last, go to first desktop
    if (current = last_desktop) {
        MoveOrGotoDesktopNumber(0)
    } else {
        MoveOrGotoDesktopNumber(current + 1)
    }
    return
}

GoToDesktopNumber(num) {
    global GoToDesktopNumberProc
    DllCall(GoToDesktopNumberProc, "Int", num, "Int")
    return
}
MoveOrGotoDesktopNumber(num) {
    ; If user is holding down Mouse left button, move the current window also
    if (GetKeyState("LButton")) {
        MoveCurrentWindowToDesktop(num)
    } else {
        GoToDesktopNumber(num)
    }
    return
}
;------------------VirtualDesktopAccessor------------------

!Capslock:: ;ALT+CapsLock
{
    GoToNextDesktop()
}
-1

I got around the issue with having to press and release the hotkeys by changing the script so it binds the hotkeys when run and never unbinds them.

1
  • Please clarify and add a little more context to this answer to convey what you are suggesting exactly. You know, consider adding some reference to this answer supporting what you state. Otherwise, read over "Why do I need 50 reputation to comment" to ensure you understand how you can start commenting. Commented Aug 11, 2017 at 16:47
-1

To switch virtual desktops, you can also assign the middle mouse button (wheel) to the side tilt. Many mouses have horizontal scrolling, but I don't use this functionality.

For example, using the X-Mouse Button Control I have the left scroll set to “Virtual Desktop: Switch Right”, and the right scroll set to “Simulated Keys” with the script: {CTRL}{ALT}{HOME}{WAITMS:500}{CTRL}{LWIN}{LEFT}

I found it very convenient.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .