Ctrl+Tab toggle between last two windows like Alt+Tab #1302

Closed
opened 2026-01-30 22:21:44 +00:00 by claunia · 19 comments
Owner

Originally created by @DavidMRCS on GitHub (May 24, 2019).

Originally assigned to: @leonMSFT on GitHub.

Ctrl+Tab allows you to move forward through open tabs. I'd like an option that works like Alt+Tab so I can just press Ctrl+Tab once to go to a previous tab and Ctrl+Tab a second time to go back to the current tab.

Originally created by @DavidMRCS on GitHub (May 24, 2019). Originally assigned to: @leonMSFT on GitHub. Ctrl+Tab allows you to move forward through open tabs. I'd like an option that works like Alt+Tab so I can just press Ctrl+Tab once to go to a previous tab and Ctrl+Tab a second time to go back to the current tab.
Author
Owner

@zadjii-msft commented on GitHub (May 24, 2019):

I'm pretty sure Ctrl+Shift+tab will take you back to the previous tab.

Now, cycling through the tabs in the order that they were last activated, as opposed to linearly through the list of tabs is certainly an interesting idea. It'd definitely have to be a separate setting from the current behavior, since some people are going to like it the current way, while others will like it the way you described.

@zadjii-msft commented on GitHub (May 24, 2019): I'm pretty sure Ctrl+Shift+tab will take you back to the previous tab. Now, cycling through the tabs in the order that they were last activated, as opposed to linearly through the list of tabs is certainly an interesting idea. It'd definitely have to be a separate setting from the current behavior, since some people are going to like it the current way, while others will like it the way you described.
Author
Owner

@jugglingcats commented on GitHub (Jun 26, 2019):

I think the OP wants most-recent-used (MRU) behaviour. Therefore having Ctrl+Shift+Tab take you to previous does not meet this requirement as it is still tab order, not MRU order.

The key binding at the moment is:

            {
                "command" : "nextTab",
                "keys" : 
                [
                    "ctrl+tab"
                ]
            }

It would be great if an mruTab command could be added so that people could bind it to Ctrl+Tab even if it isn't the default behaviour.

One thing worth mentioning is that Alt+Tab has a subtle but important behaviour: when you hold down Alt and then hit Tab repeatedly, it cycles through the MRU list until you release Alt at which point the window switch is made and the MRU list updated. This is also evidenced in apps that support Ctrl+Tab with MRU behaviour, eg. the excellent ConEmu...

@jugglingcats commented on GitHub (Jun 26, 2019): I think the OP wants most-recent-used (MRU) behaviour. Therefore having Ctrl+Shift+Tab take you to previous does not meet this requirement as it is still _tab order_, not MRU order. The key binding at the moment is: ``` { "command" : "nextTab", "keys" : [ "ctrl+tab" ] } ``` It would be great if an `mruTab` command could be added so that people could bind it to Ctrl+Tab even if it isn't the default behaviour. One thing worth mentioning is that Alt+Tab has a subtle but important behaviour: when you hold down Alt and then hit Tab repeatedly, it cycles through the MRU list _until you release Alt_ at which point the window switch is made and the MRU list updated. This is also evidenced in apps that support Ctrl+Tab with MRU behaviour, eg. the excellent ConEmu...
Author
Owner

@jozsefhabit commented on GitHub (Aug 3, 2019):

I would like to see this one as well. Switching between the actual and the last viewed tab with the same shorcut is a big time saver. This should be a separate setting though. preserving the old behavior of the nextTab and prevTab, something like this:
{ "command" : "nextTab", "keys" : [ "ctrl+tab" ] }, { "command" : "prevTab", "keys" : [ "ctrl+shift+tab" ] }, { "command" : "LastTab", "keys" : [ "shift+tab" ] },

@jozsefhabit commented on GitHub (Aug 3, 2019): I would like to see this one as well. Switching between the actual and the last viewed tab with the same shorcut is a big time saver. This should be a separate setting though. preserving the old behavior of the nextTab and prevTab, something like this: ` { "command" : "nextTab", "keys" : [ "ctrl+tab" ] }, { "command" : "prevTab", "keys" : [ "ctrl+shift+tab" ] }, { "command" : "LastTab", "keys" : [ "shift+tab" ] }, `
Author
Owner

@fschmied commented on GitHub (Sep 14, 2019):

I think MRU tab switching for both Ctrl+Tab and Ctrl+Shift+Tab (the latter cycling the MRU stack in reverse order) should be the default behavior because

  • it's been the default for multi-document interfaces (tabbed windows) in Windows for a long time (see, e.g., Visual Studio/SQL Server Management Studio, Notepad++, or MFC-based applications that use MDI),
  • it's symmetric with Windows' own Alt+Tab, and
  • it's "better" user experience because it leverages short-term memory/work context.

Here are some examples for the last item:

  • You are working in a terminal tab and need to look something up on another tab, then switch back.
  • You need to switch between two tabs a lot because of copying different items from one to the other or because of comparing some text.

To me, there doesn't seem to be a use case where left-to-right (rather than MRU) is the "better" behavior?

BTW, MRU should also be the default when closing tabs: Have a number of tabs open. From the first one, open a new tab. Close it again. Where are you now? Not where you were before. (This argument was borrowed from https://bugs.chromium.org/p/chromium/issues/detail?id=5569#c79.)

@fschmied commented on GitHub (Sep 14, 2019): I think MRU tab switching for both `Ctrl+Tab` and `Ctrl+Shift+Tab` (the latter cycling the MRU stack in reverse order) should be the default behavior because - it's been the default for multi-document interfaces (tabbed windows) in Windows for a long time (see, e.g., Visual Studio/SQL Server Management Studio, Notepad++, or MFC-based applications that use MDI), - it's symmetric with Windows' own `Alt+Tab`, and - it's "better" user experience because it leverages short-term memory/work context. Here are some examples for the last item: - You are working in a terminal tab and need to look something up on another tab, then switch back. - You need to switch between two tabs a lot because of copying different items from one to the other or because of comparing some text. To me, there doesn't seem to be a use case where left-to-right (rather than MRU) is the "better" behavior? BTW, MRU should also be the default when closing tabs: Have a number of tabs open. From the first one, open a new tab. Close it again. Where are you now? Not where you were before. (This argument was borrowed from https://bugs.chromium.org/p/chromium/issues/detail?id=5569#c79.)
Author
Owner

@ptyork commented on GitHub (Oct 30, 2019):

For what it's worth, I spent a good 5 hours or so trying to make this happen so I could issue a PR. It is HARD, at least for someone who hasn't really done C++ since MFC and OLE were all the rage with the cool kids. @jugglingcats last note is the real sticking point.

Easy parts:

  • Add NextTabMru and PrevTabMru bindings and such across the board.
  • Create a "local" MRU stack for the tab indexes

Moderate:

  • Add event handler for TermControl PreviewKeyUp event
  • Modify IKeyBindings to add a NotifyModifierReleased method so that this event can report this back to AppKeyBindings

Impossible for lil' ol' me (without a hideous hack):

  • Differentiate between a "click" tab change and a keyboard shortcut tab change in the TerminalPage OnTabSelectionChanged handler so that I can determine when to move the selected tab to the top of the MRU stack (should ONLY happen on a click or after control is released).
  • Figure out a non-hack, architecturally consistent way to "share" the MRU stack between TerminalPage and AppKeyBindings

Really, this should all be done such that an MRU change doesn't actually change the selected tab at all until you release the control key (or whatever modifiers you've defined). This would make it trivial to manage the stack. BUT it would require a pop-up control (listbox, listview, etc.) to show and cycle through open tabs. Same as VS and VS Code (and Firefox...only browser I can use since it supports MRU tab switching). And I'd give it a go personally, but adding GUI elements in C++ Win UI is way out of my comfort zone.

I'm 100% with @fschmied. MRU tab switching should be the default. Period. SO much more intuitive and consistent from an HCI perspective. Not sure when folks started to move away from it and whether it was just because it is by far "easier" to just cycle left to right. But it is a very bad trend, IMO.

@ptyork commented on GitHub (Oct 30, 2019): For what it's worth, I spent a good 5 hours or so trying to make this happen so I could issue a PR. It is HARD, at least for someone who hasn't really done C++ since MFC and OLE were all the rage with the cool kids. @jugglingcats last note is the real sticking point. Easy parts: - Add NextTabMru and PrevTabMru bindings and such across the board. - Create a "local" MRU stack for the tab indexes Moderate: - Add event handler for TermControl PreviewKeyUp event - Modify IKeyBindings to add a NotifyModifierReleased method so that this event can report this back to AppKeyBindings Impossible for lil' ol' me (without a hideous hack): - Differentiate between a "click" tab change and a keyboard shortcut tab change in the TerminalPage OnTabSelectionChanged handler so that I can determine when to move the selected tab to the top of the MRU stack (should ONLY happen on a click or after control is released). - Figure out a non-hack, architecturally consistent way to "share" the MRU stack between TerminalPage and AppKeyBindings Really, this should all be done such that an MRU change doesn't actually change the selected tab at all until you release the control key (or whatever modifiers you've defined). This would make it trivial to manage the stack. BUT it would require a pop-up control (listbox, listview, etc.) to show and cycle through open tabs. Same as VS and VS Code (and Firefox...only browser I can use since it supports MRU tab switching). And I'd give it a go personally, but adding GUI elements in C++ Win UI is way out of my comfort zone. I'm 100% with @fschmied. MRU tab switching should be the default. Period. SO much more intuitive and consistent from an HCI perspective. Not sure when folks started to move away from it and whether it was just because it is by far "easier" to just cycle left to right. But it is a very bad trend, IMO.
Author
Owner

@DHowett-MSFT commented on GitHub (Oct 30, 2019):

Hey @ptyork, thanks for looking into this!

Regarding sharing state between Page and AppKeyBindings, this might help: Bindings should architecturally only emit events to which page can subscribe. The event callbacks are in AppActionHandlers, which is actually a poorly-named file that contains all of the event handlers in TerminalPage.

It's our bad that TermControl has to know about key bindings at all. Sorry! I actually thought we were tracking this in a workitem somewhere, so that's homework for me. 😄

@DHowett-MSFT commented on GitHub (Oct 30, 2019): Hey @ptyork, thanks for looking into this! Regarding sharing state between Page and AppKeyBindings, this might help: Bindings should architecturally only emit events to which page can subscribe. The event callbacks are in AppActionHandlers, which is actually a poorly-named file that contains all of the event handlers in _TerminalPage_. It's our bad that TermControl has to know about key bindings at all. Sorry! I actually thought we were tracking this in a workitem somewhere, so that's homework for me. :smile:
Author
Owner

@pbradshawAUS commented on GitHub (Sep 24, 2020):

Just adding a comment here that this NEEDS to happen. MRU tab-switching order is the standard, and there are DECADES of muscle-memory associated with them. The only application that doesn't do this is Chrome, and it's why I hate using Chrome (and now EDGE). EVERY other tabbed UI in the universe does this the right way... MRU tab switching. If you have more than two tabs open, the "just switch to the left/right" tab switching is utterly annoying and useless, and introduces too high of a cognitive load to try and remember where you are, where you want to go, and whether you should use Ctrl-Tab or Shift-Ctrl-Tab to get there. It's just horrible usability, and I curse Chrome every day for not implementing at least the OPTION of having MRU tab switching (as IE did, and as FireFox does). It should be verboten to introduce any kind of tabbed UI without this option. This should be a high-priority addition. There are tons of examples of how this should work already, so all the usecases and edgecases should be taken care of (Visual Studio, SQL Server Management studio, Notepad++, FireFox (with the option turned on in settings), IE11 (with the option turned on in settings), Alt-Tab behavior in Windows itself, etc.

@pbradshawAUS commented on GitHub (Sep 24, 2020): Just adding a comment here that this NEEDS to happen. MRU tab-switching order is the standard, and there are DECADES of muscle-memory associated with them. The only application that doesn't do this is Chrome, and it's why I hate using Chrome (and now EDGE). EVERY other tabbed UI in the universe does this the right way... MRU tab switching. If you have more than two tabs open, the "just switch to the left/right" tab switching is utterly annoying and useless, and introduces too high of a cognitive load to try and remember where you are, where you want to go, and whether you should use Ctrl-Tab or Shift-Ctrl-Tab to get there. It's just horrible usability, and I curse Chrome every day for not implementing at least the OPTION of having MRU tab switching (as IE did, and as FireFox does). It should be verboten to introduce any kind of tabbed UI without this option. This should be a high-priority addition. There are tons of examples of how this should work already, so all the usecases and edgecases should be taken care of (Visual Studio, SQL Server Management studio, Notepad++, FireFox (with the option turned on in settings), IE11 (with the option turned on in settings), Alt-Tab behavior in Windows itself, etc.
Author
Owner

@ghost commented on GitHub (Nov 11, 2020):

:tada:This issue was addressed in #7952, which has now been successfully released as Windows Terminal v1.4.3141.0.🎉

Handy links:

@ghost commented on GitHub (Nov 11, 2020): :tada:This issue was addressed in #7952, which has now been successfully released as `Windows Terminal v1.4.3141.0`.:tada: Handy links: * [Release Notes](https://github.com/microsoft/terminal/releases/tag/v1.4.3141.0) * [Store Download](https://www.microsoft.com/store/apps/9n8g5rfz9xk3?cid=storebadge&ocid=badge)
Author
Owner

@ghost commented on GitHub (Nov 11, 2020):

:tada:This issue was addressed in #7952, which has now been successfully released as Windows Terminal Preview v1.5.3142.0.🎉

Handy links:

@ghost commented on GitHub (Nov 11, 2020): :tada:This issue was addressed in #7952, which has now been successfully released as `Windows Terminal Preview v1.5.3142.0`.:tada: Handy links: * [Release Notes](https://github.com/microsoft/terminal/releases/tag/v1.5.3142.0) * [Store Download](https://www.microsoft.com/store/apps/9n8g5rfz9xk3?cid=storebadge&ocid=badge)
Author
Owner

@nsballmann commented on GitHub (Nov 13, 2020):

How do I return to Pre-MRU behavior? I somehow can't find it in the documentation.

@nsballmann commented on GitHub (Nov 13, 2020): How do I return to Pre-MRU behavior? I somehow can't find it in the documentation.
Author
Owner

@Don-Vito commented on GitHub (Nov 13, 2020):

How do I return to Pre-MRU behavior? I somehow can't find it in the documentation.

@nsballmann - in 1.5 Preview you can set "tabSwitcherMode" in global settings.
The available values are "mru", "inOrder", "disabled". I guess you are looking for "inOrder"

In 1.4 (as @kwburnett suggested below) you can fully disable the tab switcher with "useTabSwitcher" set to false, which will also fallback to the "inOrder" behavior, but you won't see tab switching UI.

@Don-Vito commented on GitHub (Nov 13, 2020): > > > How do I return to Pre-MRU behavior? I somehow can't find it in the documentation. @nsballmann - in 1.5 Preview you can set ``"tabSwitcherMode"`` in global settings. The available values are ``"mru", "inOrder", "disabled"``. I guess you are looking for ``"inOrder"`` In 1.4 (as @kwburnett suggested below) you can fully disable the tab switcher with ``"useTabSwitcher"`` set to ``false``, which will also fallback to the "inOrder" behavior, but you won't see tab switching UI.
Author
Owner

@kwburnett commented on GitHub (Nov 13, 2020):

How do I return to Pre-MRU behavior? I somehow can't find it in the documentation.

@nsballmann - you can set "tabSwitcherMode" in global settings.
The available values are "mru", "inOrder", "disabled". I guess you are looking for "inOrder"

This didn't work for me. However, setting "useTabSwitcher" to false in the global settings did the trick.

@kwburnett commented on GitHub (Nov 13, 2020): > > How do I return to Pre-MRU behavior? I somehow can't find it in the documentation. > > @nsballmann - you can set `"tabSwitcherMode"` in global settings. > The available values are `"mru", "inOrder", "disabled"`. I guess you are looking for `"inOrder"` This didn't work for me. However, setting `"useTabSwitcher"` to `false` in the global settings did the trick.
Author
Owner

@Don-Vito commented on GitHub (Nov 13, 2020):

How do I return to Pre-MRU behavior? I somehow can't find it in the documentation.

@nsballmann - you can set "tabSwitcherMode" in global settings.
The available values are "mru", "inOrder", "disabled". I guess you are looking for "inOrder"

This didn't work for me. However, setting "useTabSwitcher" to false in the global settings did the trick.

@kwburnett - I was addressing 1.5 Preview. In 1.4 you can turn off tab switcher completely (the way you did with "useTabSwitcher"), but it will hide the tab switcher UI as well.

@Don-Vito commented on GitHub (Nov 13, 2020): > > > > > How do I return to Pre-MRU behavior? I somehow can't find it in the documentation. > > > > > > @nsballmann - you can set `"tabSwitcherMode"` in global settings. > > The available values are `"mru", "inOrder", "disabled"`. I guess you are looking for `"inOrder"` > > This didn't work for me. However, setting `"useTabSwitcher"` to `false` in the global settings did the trick. @kwburnett - I was addressing 1.5 Preview. In 1.4 you can turn off tab switcher completely (the way you did with ``"useTabSwitcher"``), but it will hide the tab switcher UI as well.
Author
Owner

@nsballmann commented on GitHub (Nov 13, 2020):

Currently I'm on 1.4. I just put both into my config, so it will be easy for me, when 1.5 goes from preview to release.

{
  "useTabSwitcher": false,
  "tabSwitcherMode": "inOrder"
}

Thank you both very much, @Don-Vito and @kwburnett .

@nsballmann commented on GitHub (Nov 13, 2020): Currently I'm on *1.4*. I just put both into my config, so it will be easy for me, when *1.5* goes from *preview* to *release*. ```json { "useTabSwitcher": false, "tabSwitcherMode": "inOrder" } ``` Thank you both very much, @Don-Vito and @kwburnett .
Author
Owner

@ofseed commented on GitHub (Jan 31, 2021):

Is there a way to disable ctrl+tab and ctrl+shift+tab 's functions? There are some conflict between others...setting
useTabSwitcher to false is not to display the switching window.

@ofseed commented on GitHub (Jan 31, 2021): Is there a way to disable ```ctrl+tab``` and ```ctrl+shift+tab``` 's functions? There are some conflict between others...setting ```useTabSwitcher``` to false is not to display the switching window.
Author
Owner

@Don-Vito commented on GitHub (Jan 31, 2021):

@1478zhcy - you can unbind a keys combination by creating a binding and setting the command name to unbound. Please see: https://docs.microsoft.com/en-us/windows/terminal/customize-settings/actions#unbind-keys

Something like

{ "command": "unbound", "keys": "ctrl+tab" },
{ "command": "unbound", "keys": "ctrl+shfit+tab" }

In 1.5 these bindings are still hard-coded within tab switcher (should not affect most cases - but if it does, you can hide the tab switcher). In 1.6 Preview everything should simply work.

@Don-Vito commented on GitHub (Jan 31, 2021): @1478zhcy - you can unbind a keys combination by creating a binding and setting the command name to `unbound`. Please see: https://docs.microsoft.com/en-us/windows/terminal/customize-settings/actions#unbind-keys Something like ``` { "command": "unbound", "keys": "ctrl+tab" }, { "command": "unbound", "keys": "ctrl+shfit+tab" } ``` In 1.5 these bindings are still hard-coded within tab switcher (should not affect most cases - but if it does, you can hide the tab switcher). In 1.6 Preview everything should simply work.
Author
Owner

@ofseed commented on GitHub (Jan 31, 2021):

@Don-Vito Thank you very much! It works. But after that setting, I just found out it seems that terminals don't see a difference between tab and ctrl+tab, So I still can't use they in console applications.🤣

@ofseed commented on GitHub (Jan 31, 2021): @Don-Vito Thank you very much! It works. But after that setting, I just found out it seems that terminals don't see a difference between ```tab``` and ```ctrl+tab```, So I still can't use they in console applications.🤣
Author
Owner

@Don-Vito commented on GitHub (Jan 31, 2021):

@1478zhcy - I see. Please address the discussion in https://github.com/microsoft/terminal/issues/8931. As it might be relevant as well.

@Don-Vito commented on GitHub (Jan 31, 2021): @1478zhcy - I see. Please address the discussion in https://github.com/microsoft/terminal/issues/8931. As it might be relevant as well.
Author
Owner

@ofseed commented on GitHub (Feb 1, 2021):

@Don-Vito Thank you!

@ofseed commented on GitHub (Feb 1, 2021): @Don-Vito Thank you!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#1302