Skip to content
 
 

Repository files navigation

Switchy

Switchy

A lightweight utility to toggle between two specific keyboard layouts using Caps Lock (or any other specified key).

Unlike the standard Windows behavior (which cycles through all installed layouts), Switchy allows you to define exactly two main layouts in a configuration file.
Pressing the key will instantly toggle between them, ignoring any other layouts installed on the system.

switchy

Layout switching targets the focused control when possible (GetGUIThreadInfo + SendMessageTimeout with WM_INPUTLANGCHANGEREQUEST), with fallbacks documented in code. This avoids relying only on PostMessage to the top-level window (which often fails in modal dialogs such as Save As). It still does not show the Windows 10/11 language pop-up by default.

Usage

MSI installer (recommended)

  1. Download switchy.msi from the Releases page.
  2. Run the installer - switchy.exe and the switchy.default.ini template are placed in %ProgramFiles%\Switchy\ and autostart is registered via the current user's Run key.
  3. The application starts automatically once the installation is complete.

To configure, edit %LOCALAPPDATA%\Switchy\switchy.ini (see below) - it is created from the template on each user's first run. Upgrades update the template but never touch per-user configs; uninstall keeps them too.

Manual install

  1. Download switchy.exe and switchy.default.ini from the Releases page.
  2. For a portable setup, copy switchy.default.ini to switchy.ini next to switchy.exe and edit it (see below). Without it the config is created in %LOCALAPPDATA%\Switchy\.
  3. Run switchy.exe.

Controls

  • Caps Lock (default): Switch between Layout 1 and Layout 2.

  • Shift + Caps Lock: Toggle actual Caps Lock state (upper case mode).

  • Alt + Caps Lock: Enable/Disable Switchy temporarily.

  • Ctrl + Caps Lock (when ConvertWithCtrl=1): Select text in the focused field, then press this chord to re-translate the selection as if it had been typed on the other layout, paste the result, and switch to that layout. (Use explicit selection; there is no keystroke buffer.)

  • SmartCaps=1: plain Caps Lock runs a synthetic copy; conversion runs only if the Unicode clipboard changes after that copy (so an old clip is not mistaken for a selection). Layout always switches. With Ctrl held, the layout switches even when nothing is selected. Clipboard is backed up and restored; very large clips (over ~1M characters) skip conversion and only switch layout.

  • Tray icon: opens the settings dialog (edits all [Settings] keys and process exclusions), Reload config (shown when AutoReload=0), Enable/Disable, About (version and update check), Exit.

Note

If you changed the SwitchKey in the config, replace "Caps Lock" with your chosen key in the instructions above.

Auto-start

The MSI installer registers autostart automatically (HKCU\Software\Microsoft\Windows\CurrentVersion\Run).

For a manual install, add Switchy to the startup folder:

  1. Press Win+R, type shell:startup, and press Enter.
  2. Create a shortcut to switchy.exe in that folder.

Note

For keyboard switching to work inside programs running as Administrator (e.g., Task Manager, RegEdit), Switchy must also be run as Administrator.
You can set this up via Windows Task Scheduler.

Configuration (switchy.ini)

Active config: switchy.ini next to switchy.exe if that directory is writable (portable mode), otherwise %LOCALAPPDATA%\Switchy\switchy.ini. A legacy config next to the executable (e.g. in %ProgramFiles%\Switchy\) is copied to the per-user location on first run. Edits apply on the fly (AutoReload=1).

Tip

If you leave Layout1 or Layout2 empty (or delete the lines), Switchy will automatically use your system's default keyboard layouts for them.

[Settings]
; Config format version. Do not change; files without this key are treated
; as legacy (version 0) and load the same way. Versions above 1 are rejected.
ConfigVersion=1

; Exact Windows keyboard layout IDs (KLID), 8 hex digits.
; Standard layout codes:
; 00000409 = English (US)
; 00000419 = Russian
; 00000422 = Ukrainian
; 00000407 = German
; 0000040C = French
; Custom MSKLC layouts have their own KLID, not just the language code
; (e.g. Layout1=a0000409, Layout2=a0000419) - see below for how to find it.
; Leave both empty for auto-detection: works only if exactly two system
; layouts are loaded, or more are loaded but exactly two distinct languages
; are unambiguous. Otherwise Switchy refuses to start and asks for explicit
; KLIDs here.
Layout1=00000409
Layout2=00000419

; The Virtual Key Code for switching (Decimal).
; 20 = Caps Lock (Default)
; 19 = Pause/Break
; 45 = Insert
; 112 = F1
SwitchKey=20

; 1 = Ctrl + SwitchKey converts selected text (see above). 0 = Ctrl+key does nothing special.
ConvertWithCtrl=1

; 1 = smart Caps (see above). 0 = plain Caps only toggles layout.
SmartCaps=0

; If the normal layout request fails: 0 = none, 1 = Alt+Shift cycle, 2 = Ctrl+Shift cycle,
; 3 = Win+Space (language bar). Your Windows "switch input language" hotkey may differ.
FallbackCycleHotkey=0

; Timeout (ms) for the SendMessageTimeout layout-switch request.
; Lower values reduce first-letter lag on fast typing. Range: 10-2000.
SwitchTimeoutMs=80

; Suppress layout switch for fullscreen / borderless foreground windows (games).
; Bit flags: 0 = off (default), 1 = fullscreen, 2 = borderless (no title bar), 3 = both.
FullScreenExcludeSwitch=0

; Same flags for text conversion (Ctrl+SwitchKey / SmartCaps).
FullScreenExcludeConvert=0

; 1 = show the tray icon (menu: Settings, Reload config when AutoReload=0,
;     Enable/Disable, About, Exit).
; 0 = no icon; switching still works, set back to 1 here to bring it back.
TrayIcon=1

; 1 = watch this file and apply changes on the fly (no restart needed).
; 0 = re-read only via "Reload config" in the tray menu (the item is
;     shown only in this mode).
AutoReload=1

; UI language: auto (follow Windows), en, ru, uk, de, fr.
; Unknown values fall back to English.
Language=auto

; 1 = write diagnostics (resolved layouts, every switch attempt) to
;     switchy.log next to this file. Off by default; enable only while
;     troubleshooting, the log grows on every switch.
Debug=0

Troubleshooting

Set Debug=1 in switchy.ini to get a switchy.log next to the active config: which layouts were detected at startup (including the Preload language order used for auto-detection), and, for every switch attempt, the current layout, the computed target, and the result of each activation step. Turn it back off once done - the log is appended to on every switch.

Optional: exclude processes

ExcludeSwitch disables layout switching;
ExcludeConvert disables the Ctrl+SwitchKey conversion.
Listing an exe in both disables both behaviors for that process.

The value controls the scope of suppression:

  • (empty) or 1 - Suppress only when this app's window is active (default)
  • 0 - Suppress whenever this process is running anywhere (global)

Both lists can also be edited in the settings dialog, which includes a Spy++-style crosshair picker: drag it onto a window to add that application without typing the executable name.

[ExcludeSwitch]
; Suppress layout switch when the app window is active (default per-window mode):
SomeApp.exe=
; Same, explicit:
SomeApp.exe=1
; Suppress layout switch whenever the app is running, even in background:
SomeApp.exe=0

[ExcludeConvert]
SomeApp.exe=

Limitations

  • Conversion covers typical letters, digits, and basic Shift/AltGr mappings built from the two configured layouts. Dead keys and exotic compose sequences are not promised.
  • Clipboard: only the Unicode text (CF_UNICODETEXT) is restored around copy/paste; other clipboard formats may be dropped during the operation.
  • UIPI: synthetic input may not reach elevated or protected targets unless Switchy runs with sufficient integrity.
  • Layouts: the two layouts are distinguished by full HKL handles, so variants of the same language (e.g. US QWERTY vs Dvorak) are supported.

How to find Keyboard Layout IDs?

You need the Input Locale Identifier (KLID) for your desired languages. For custom layouts (e.g. built with MSKLC), this is not the same as the plain language code - a custom layout gets its own KLID (commonly starting with a or d, e.g. a0000409).

  1. Registry Method (Most Accurate): Open Registry Editor (regedit) and navigate to: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts Look through the keys; the Layout Text value will tell you the language name. Copy the folder name (e.g., 00000409).

    Or list every installed layout at once with PowerShell:

    $root = 'HKLM:\SYSTEM\CurrentControlSet\Control\Keyboard Layouts'
    
    Get-ChildItem $root | ForEach-Object {
        $p = Get-ItemProperty $_.PSPath
    
        [pscustomobject]@{
            KLID     = $_.PSChildName
            Name     = $p.'Layout Text'
            File     = $p.'Layout File'
            LayoutId = $p.'Layout Id'
        }
    } | Sort-Object Name | Format-Table -Auto
  2. Preload / Substitutes: Which layouts are actually loaded for your user, and how custom layouts are mapped to a requested language, is controlled by:

    reg query "HKCU\Keyboard Layout\Preload"
    reg query "HKCU\Keyboard Layout\Substitutes"

    Substitutes entries are requested KLID = actual KLID (e.g. d0010419 = a0000419). The value Switchy needs in switchy.ini is the actual KLID - the right-hand side - not the requested one.

  3. Microsoft Docs: You can look up Language Identifiers here: Language Identifier Constants and Strings, Windows Language Code Identifier (LCID) Reference You usually need the last 4 digits padded with zeros (e.g., 0x0409 -> 00000409).

How to find Key Codes?

If you want to use a key other than Caps Lock, you need its Microsoft Virtual-Key Codes.

Example: If you want to use Right Alt, the constant is VK_RMENU, the value is 0xA5 (Hex), which is 165 in Decimal.

Building from source

This fork uses standard C API and does not require Visual Studio. You can build it using GCC (MinGW).

make          # clean -> test -> build -> msi
make build    # exe only
make test     # unit tests
make msi      # MSI installer (requires WiX 7: dotnet tool install --global wix)
# or manually:
gcc src/*.c -o switchy.exe -mwindows -O2 -std=c99 -luser32 -lkernel32 -ladvapi32 -lshell32 -lole32

Example custom layouts

klc/ has example MSKLC .klc source files (Russian, Ukrainian, Belarusian, Kazakh) with a shared "coder" AltGr extension - see klc/README.md.

Releases

Contributors

Languages