19 KiB
KSwitcher
Native C++20 / Win32 rewrite of the Windows functionality of Typlo. Windows 10/11 x64. No .NET, Avalonia, WebView, Qt, external graphics engine, or separately installed C++ runtime. The original Typlo project and its data remain separate.
User guide / Wiki — setup, features, shortcuts, dictionaries, screenshots and troubleshooting (Ukrainian).
Run
Run build/KSwitcher.exe, or extract dist/KSwitcher-win-x64.zip and run the executable.
The build also refreshes the release copy in build/release/. Exit KSwitcher before rebuilding.
The application lives in the notification area. Right-click its icon for Settings, Snippets and history.
Double-click the tray icon to open Settings, the bold default menu item.
Settings and the snippet editor run on demand in KSwitcher.Config.exe, beside the main executable.
Repeated launches activate the existing configurator; closing its last window exits that process.
Saving applies changes immediately through the resident KSwitcher process. The configurator does not
load clipboard history, dictionaries or global input hooks. Clipboard history and the log viewer remain
in the resident app. Keep both executables together when copying or updating the application.
If settings change in the tray while the configurator is open, a conflicting Save is rejected; reopen
the configurator to load the latest settings.
The first upgrade from v0.2.3 or earlier to this two-executable build requires manual extraction:
the older updater rejects additional executable files. Exit KSwitcher, replace both executables,
and retain data/ and customized dictionaries. Subsequent updates support both executables.
In Settings, enable Start with Windows and Start with Windows as administrator
to use a per-user Task Scheduler logon task with highest privileges. Enabling or changing
the elevated task requests UAC approval if the app is not already elevated. No password is stored;
the task runs in the signed-in user's interactive session, including on battery power.
Disabling the administrator option restores ordinary per-user startup; disabling startup stops
future automatic launches. Saving unrelated settings does not recreate startup entries.
KSwitcher.exe --settings opens Settings, including when the app is already running.
Exit Typlo when using overlapping shortcuts to avoid competing keyboard hooks.
Change a shortcut
- Open Settings and click a shortcut field.
- Press the desired combination. The field records the actual keys; no typing of names is needed.
- Click Save. Duplicate shortcuts within KSwitcher and protected Windows combinations are reported.
This also works for each layout's Direct layout shortcut. Backspace or Delete without modifiers clears a shortcut. Tab moves to the next field. The recorded shortcut is suppressed while the field has focus, so recording the conversion shortcut does not perform a conversion. All configured shortcuts use the existing keyboard hook and can replace ordinary Windows/app shortcuts, including Win+V and Win+Shift+S, while KSwitcher is running. Only exact configured combinations are intercepted. Unassigned shortcuts and simulated copy/paste pass through. Choose another shortcut or exit KSwitcher to restore the original action. Windows protects Ctrl+Alt+Delete and Win+L; these cannot be assigned.
Keyboard and mouse input forwarded by Microsoft Mouse Without Borders follows the same input path as a local keyboard/mouse, including shortcuts, recent-word conversion and snippets. KSwitcher marks its own generated input so copy/paste, selection, modifier releases and shell-mask keys cannot trigger recursive commands or overwrite the recorded typing run. Other injected input is accepted, including key-up events and VK-only keyboard events. Unicode packets do not provide physical key positions and therefore reset recent-word tracking; selection conversion still works.
Updates
Select Update in the tray menu to check the stable Releases of
this repository.
A startup check also reports an available version, but never installs it automatically.
Confirm the offered version to download and install it. The updater uses the existing
KSwitcher-win-x64.zip and SHA256SUMS.txt assets, checks the checksum, package contents, x64
executable identity and version, then closes and restarts KSwitcher. Downloads and staging happen
before the application exits. If replacement or startup fails, it restores the previous files;
if recovery itself fails, it reports the retained backup directory.
Saved settings and clipboard history in data/ or the local-app-data fallback are preserved.
Existing dictionary files are preserved too; missing dictionary files are installed. Save settings
edits before updating. The installation directory must be writable at KSwitcher's current privilege
level. A blocked network request, incomplete release or checksum mismatch leaves the running version
intact and is reported when Update is selected. Startup network failures remain non-interactive.
The helper uses Windows' built-in Windows PowerShell 5.1; no additional runtime is installed.
Settings and the other utility windows use the destination monitor's DPI for their initial frame, controls and fonts. They can be resized, stay within a remaining monitor's work area after display changes, and provide scrollbars when their content does not fit. Tab navigation scrolls the focused field into view; Shift+wheel scrolls horizontally.
Implemented
- Installed Windows keyboard layouts, configurable cycle/order and direct shortcuts; IMEs are switch-only.
- Selection conversion and verified recent input (physical scan codes, 2-second typing-run boundary).
- Same-process clipboard ownership plus verified WebView2 descendants, including the Teams fix.
- Teams recent-word conversion uses a single word-selection command and validates the copied range. If the editor's word boundary differs from the recorded typing, it falls back to paced character selection: Teams can coalesce a burst of Shift+Left events into just one character.
- Clipboard snapshot/restoration with concurrent-copy, foreground and input-version checks.
- Case cycling, Russian/Ukrainian transliteration, verified undo and repeated conversion.
- Text snippets across layouts, multiline insertion and a verified
{cursor}position;{{cursor}}inserts the literal marker. Snippets are stored as plaintext settings, as in Typlo. - Clipboard history for text, HTML/RTF, file lists, DIB and PNG images; plain-text paste; full-text search, pinning, deletion, full text viewing and image previews.
- Image thumbnails and text/file icons appear directly in the history list. Only visible rows load thumbnails; the 32-entry thumbnail cache is bounded to about 3.3 MiB and released on close.
- Text rows render RTF and basic clipboard HTML emphasis (bold, italic, underline, strike-through), paragraphs, line breaks and list bullets using native Windows RichEdit. Previews are bounded to 4096 characters / 64 KiB RTF, with at most 32 cached text previews; original paste formats are unchanged. HTML is parsed as text, without a browser, scripts or external resources. Complex web layouts and stylesheet rules are not reproduced; preview text uses the list's colors for readability.
- Consecutive screenshot copies are compared by image content, ignoring changing OLE transport metadata (including Snipping Tool's repeated clipboard publication).
- Windows OCR, entirely native and offline. Right-click an image in history and select Copy text from image. Requires a Windows OCR language installed for the user profile.
- History exclusion flags and excluded processes, pause/resume, count/size limits.
- Per-user Windows DPAPI encryption for both history payloads and the preview index.
- Autostart, keep-screen-awake, idle-only F15 activity signal, settings import/export.
- Single instance and
--history,--convert,--case,--transliterate,--settings,--snippets,--exitcommands.--convertcycles layouts.
Default shortcuts match Typlo: Ctrl+Alt+Shift+Space (cycle), C (case), T (transliteration), Z (undo), 1/2/3 (first layouts), and Ctrl+Shift+V (history).
History controls: Enter to paste, Shift+Enter for plain text, Ctrl+1…9 for quick paste, Ctrl+P to pin/unpin, Delete to delete, Ctrl+O for the full item, Escape to hide. Pressing the history shortcut a second time pastes the second-most-recent item.
Data and migration
Data is in data/ beside the executable, falling back to %LOCALAPPDATA%/KSwitcher when
the executable's directory is not writable. Each clipboard payload is an encrypted disk file;
only bounded previews/metadata stay in memory. Image data is loaded on demand and released when
the history popup is hidden. Settings Write log (writeLog, enabled by default) controls all
log writes. Disabling it also clears diagnostic context from memory; existing log files remain.
Successful operations stay in a memory buffer of at most 40 diagnostic events for 30 seconds.
Only failures flush this context to kswitcher.log; flushed
context is discarded. Ordinary application errors are also logged when logging is enabled.
Incident context contains tracked physical input, the expected word, copied text, conversion result,
and layout IDs, correlated by request ID even when verification fails. Text fields use quoted,
escaped UTF-16 (\uXXXX for non-ASCII and control characters) for exact reproduction, with
original length and a truncation flag; each field is limited to 512 UTF-16 code units.
Manual conversion attempts in kswitcher.log have request IDs and explicit outcomes, including
busy, empty copy, verification mismatch, unchanged conversion, and cancelled paste. Requests
record the process, window, input version, and repeated attempts within ten seconds without new
input. Successful repeated commands do not flush the log; intentional layout cycling is normal.
An unchanged result containing no letters, or a direct command
to the detected current layout, is treated as expected. paste-sent-unverified means Windows
accepted the paste shortcut; it does not prove that the editor applied the replacement.
The previous 256 KiB log is retained as kswitcher.log.1 when the current log rotates.
Open View log… from Settings or the tray menu to read logs inside KSwitcher.
Choose the current or previous log and press Refresh to reload. The ListView shows Time,
Attempt, Event, and Details columns. Select rows and use Copy selected or Ctrl+C to copy
tab-separated entries; Ctrl+A selects all rows. Viewing saved logs also works when logging is disabled.
Clear log clears only the selected current or previous file and refreshes the table.
Clearing the current log also discards buffered diagnostic context; new problems can still be logged.
Settings Import accepts a Typlo settings.json, preserving supported Windows layout IDs,
hotkeys, snippets, exclusions and limits. Import is staged until Save. Existing Typlo files are
never modified. Typlo's encrypted SQLite history is not migrated to the new DPAPI file format.
DPAPI data belongs to the Windows account/machine; copying the portable folder is not a cross-account backup.
Differences still to port
This is a working native implementation, not a claim of complete UI/release parity:
- UI currently uses English and the native Windows control appearance. Typlo's ten-language UI and explicit light/dark theme selector are not yet ported.
- No import of old encrypted clipboard history. Export/import applies to settings.
- The clipboard popup uses per-monitor DPI scaling and scrolls when space is limited; PNG/DIB previews use Windows WIC/GDI.
The Windows focus/injection rules still apply: an unelevated process cannot edit an elevated app. Conversion is cancelled rather than pasting into a different window or replacing unverified recent text.
Build
The easiest reproducible local route uses the pinned portable w64devkit toolchain:
.\setup-toolchain.ps1
.\build.ps1 -Test
.\package.ps1
setup-toolchain.ps1 downloads the compiler from its upstream GitHub release and verifies SHA-256.
.tools/, build objects, test executables and compiler headers are development-only. Do not distribute
the entire source/build folder. The package contains just the application and notices/documentation.
The vendored JSON header is nlohmann/json 3.12.0 (MIT); it is compiled into the executable.
Alternatively open this directory as a CMake project in Visual Studio with the C++ desktop workload and Windows SDK installed, or use CMake with a Windows GCC toolchain. CMake/MSVC is provided but the verified local build uses GCC/w64devkit.
Automatic layout correction (experimental)
Enable Automatically correct layout (experimental) in Settings, then use Auto-correction options… to select dictionary languages and edit excluded applications or words to never correct. The feature is off by default. English and Ukrainian are selected initially; Russian is optional. Target layouts must also be enabled in the layout cycle.
Characters before a word and Characters after a word configure punctuation to preserve around the corrected word. Enter characters directly, without spaces or separators; a comma or semicolon is itself a character. Defaults include parentheses, square/curly brackets, quotation marks and common trailing punctuation, including colon and semicolon. Empty fields disable stripping on that side. Up to three leading and six trailing characters (including the final space) are supported. Recognition still requires a verified complete word; punctuation inside a word is not stripped. Correction runs after Space, not immediately after a punctuation key. Save Settings to apply changes.
Frequency rank limit defaults to 0 (entire dictionary). A positive value allows corrections only to words with a rank at or below that number (for example, 10000). All dictionary words still protect already valid input, and ambiguous alternatives remain unchanged regardless of this limit. Open dictionary folder opens the files beside the running executable. After editing, click OK in the options window and Save in Settings to validate and reload the dictionaries without restarting. Use UTF-8, one lowercase word followed by a Tab and a positive rank per line; keep words sorted and unique. For a personal addition, rank 1 makes it eligible at every positive limit. Back up your edited files before replacing dictionaries with a new distribution.
After Space and a 250 ms typing pause, KSwitcher checks the last physically typed word against local
dictionaries. For example, ghbdsn can become привіт . Continuing to type cancels pending work.
It only corrects unknown words when exactly one alternative is a dictionary word.
Minimum word length defaults to 3 and can be set from 1 to 32 letters. Surrounding punctuation
does not count toward this minimum; the maximum word length is 32 letters.
Known words, ambiguous alternatives, ALL CAPS, mixed-case identifiers, numbers, URLs and email
addresses are left unchanged. Short trailing punctuation is retained when the editor selects it
together with the word. Actual selected text is verified before replacement. Layout switching follows
the existing switch-layout setting. The configured Undo shortcut restores the original and suppresses
that word for the rest of the session (until restart).
Password fields and inaccessible controls are skipped using Windows UI Automation. Editors, terminals and password managers are excluded by default; process names can be edited in the options window. Controls that do not expose an editable/document element or cannot select a complete word may not support automatic correction. Dictionary recognition is heuristic, not an understanding of the sentence; subtitle vocabulary is incomplete, and uncommon names or jargon can need personal exceptions.
No network service or language model is used. The three dictionary files occupy about 2.6 MB on disk;
the English/Ukrainian lookup data uses less than 3 MiB of RAM and is loaded on first automatic check.
Keep dictionaries/ beside the executable when copying the app. These word lists derive from
FrequencyWords and are separately licensed under
CC BY-SA 4.0; attribution, pinned source revision and license are in dictionaries/.
Latest compiled release
The Release folder contains the latest portable Windows x64 ZIP and SHA-256 checksum.
Run ./package.ps1 -PublishRelease after building and testing to refresh the tracked release archive.
Verification
.\build.ps1 -Test # Pure/native regression checks; does not touch the user's clipboard
.\build.ps1 -Ocr # Render a synthetic image, decode it with WIC and recognize it with Windows OCR
.\build.ps1 -Integration # Interactive, isolated test editor; avoid input for about 10 seconds
.\tests\configuration.ps1 # Separate-process settings tests; close KSwitcher first
-Test also checks remote/own input separation, hidden Settings layout and scrolling, and updater
package validation, file preservation and rollback in temporary fixture directories. It does not
replace a running installation. Optional read-only network checks:
.\build\KSwitcherInputTests.exe --update-check
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\tests\update.ps1 -Network
These validate the live release metadata/download/checksum in a temporary directory. They do not prove hardware interoperability between two laptops or a physical monitor-disconnection sequence.
The interactive test requires installed English-US and Russian layouts. It opens its own editor, tests real copy/paste, undo, repeat conversion, recent-input verification and snippet cursor placement, then restores the clipboard. Test data is stored in its own temporary directory. It never sends messages to Teams or other user applications. Do not run it while typing elsewhere.
KSwitcher.exe --smoke-test starts a normal tray instance and exits after ten seconds for idle-memory checks.
It still uses the normal instance lock; close a running KSwitcher first if measuring a fresh process.
Structure
core.*: conversion, transliteration, snippets, shortcut parsing/formatting, recent-input model.platform.*: Win32 layouts, clipboard, input, ownership, DPAPI and file primitives.storage.*: settings and encrypted, disk-backed history.app.*: message loop, hooks, background work and guarded text transactions.config_main.cpp,configuration.*: single-instance configurator and validated settings IPC.ui.cpp: native windows and shortcut recording.ocr.*: Windows WIC and OCR via the native Windows Runtime ABI.tests/: regression checks, real editor integration and OCR fixture.
Application code is MIT licensed; preserves the original Typlo attribution in LICENSE.
Dictionary data has its own CC BY-SA 4.0 license as described above.