# Keyboard Switch

Welcome to the Keyboard Switch docs!

Keyboard Switch is an application which switches typed text as if it were typed with another keyboard layout.

If you ever write some text and then realize that you have written it using a wrong layout, you don't have to delete it and start over anymore. Just select the text, press a magic key combination, and that's it!

I hope this app will make your life at least 1% easier :)

## Quick Start

### Windows

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.msi* file and run it to install the app. If your computer runs on the x64 architecture, then you should get the *x64* installer. If your computer runs on the Arm architecture, then you should get the *arm64* installer. If you're not sure, then you most likely need the *x64* installer.

After installation, the Keyboard Switch Settings app will start. It may take some time as the app will do some initial setup. If it doesn't start for some reason, then find it in the list of your apps.

In the opened app, press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> twice instead.

### macOS

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.pkg* file and run it to install the app. If your computer runs on an Apple CPU (e.g. M1) then you should get the *arm64* package. If your computer runs on an Intel CPU then you should get the *x86\_64* package.

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

Immediately upon opening the app, a dialog window should appear which says that Keyboard Switch would like to control this computer using accessibility features. The app needs this to listen to the magic key combination while running in the background, and without these permissions it won't work.

Click the *Open System Preferences* button on the dialog window. Enable the *Keyboard Switch* item. Close System Preferences and go back to the Keyboard Switch Settings app.

In the settings app, press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Option</kbd>+<kbd>Shift</kbd> twice instead.

To uninstall Keyboard Switch, you should run an uninstaller package. You can also get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

### Linux

The app is available as a deb package (for Debian-based distributions, such as Ubuntu, Mint etc.), an RPM package (for RHEL-based distributions, like Rocky Linux or Fedora, as well as SUSE), and a simple *tar.gz* file. You can get these files from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

Keyboard Switch supports X11 and Wayland (the latter is currently supported only on GNOME and KDE Plasma).

If you use the deb or RPM package, then simply install it either by double-clicking on it, or through the terminal. If you use the *tar.gz* file, the you can read about it in the [installation page](/4.4/usage-guides/installation#installing-the-app).

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

{% hint style="warning" %}
If your desktop environment is GNOME, then you should restart it before opening Keyboard Switch Settings. If you're not sure which desktop environment you're using then it's most probably GNOME since it's the default one on Ubuntu, Debian, Rocky, Fedora and others (but not Linux Mint). If you're using X11, Press <kbd>Alt</kbd>+<kbd>F2</kbd>, then type <kbd>r</kbd> and press <kbd>Enter</kbd> – this will restart GNOME. If you're using Wayland (which is most probably the case on newer versions of GNOME), then you're have to log out and log back in.
{% endhint %}

In the opened app, press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> twice instead.

## How the App Works

The app is composed of two parts: the Keyboard Switch service application and the Keyboard Switch Settings application. The service always runs in the background (and starts when you log into the system) and listens to key presses. When you press the magic key combination, it reacts by copying the selected text, transforming it, and pasting it for you. The settings app is used for configuring the service and for starting/stopping it manually.

Here are the basic steps you should take to switch the text:

* Type some text using an incorrect layout
* Realize your mistake
* Select the text (you can press <kbd>Ctrl</kbd>+`A` to select all text, or `Command`+<kbd>A</kbd> on macOS)
* Press the magic key combination (the default is pressing <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice)
* Profit

The app uses the list of your layouts in the same order as defined by the system. You can switch both forward and backward through this list. It will look at the current layout to determine how to switch text, so you shouldn't change the layout before switching. The app also automatically changes the layout, so you don't have to do it yourself.

The app uses the clipboard to get the text to transform and then puts the transformed text back into the clipboard. The app will try to preserve the text that was in the clipboard before switching and to restore it afterwards. It doesn't guarantee that the text will be restored though. Also, any non-text data (e.g., a file or a picture) will not be restored.

{% hint style="info" %}
**Note:** The app simulates pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> (or <kbd>Command</kbd>+<kbd>C</kbd> on macOS) to copy and <kbd>Ctrl</kbd>+<kbd>V</kbd> (or <kbd>Command</kbd>+<kbd>V</kbd> on macOS) to paste text. This is the default behavior for most applications. But if you are working in an app which behaves differently on those key presses (e.g., a terminal), this app will not be able to instantly switch text. You can disable this behavior and copy/paste the text manually.
{% endhint %}

## Supported Platforms

### Windows

Keyboard Switch is supported on Windows 11. It most probably works on earlier versions as well, but they are not officially supported, and issues that only appear on older versions will not be fixed.

The x64 and Arm64 architectures are both supported.

### macOS

Keyboard Switch requires macOS 10.15 or later, though it is supported only on macOS versions that are currently supported by Apple (as of October 2026, it's macOS 15, 26, and 27). It can run on unsupported versions as well, but issues that only appear on older versions will not be fixed.

The Arm64 architecture is supported. The x64 version is also available, but issues that only appear on the x64 version will not be fixed. It may be completely dropped in a future release, but for now, it stays.

### Linux

Keyboard switch is supported on Linux. X11 is supported, and Wayland is currently supported only on GNOME and KDE Plasma. [Click here](https://github.com/TolikPylypchuk/KeyboardSwitch/issues/105) to see the list of Linux distributions on which the app was tested.

The x64 and Arm64 architectures are both supported.


# Installation

## Windows

### Using a Windows Installer

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.msi* file and run it to install the app. If your computer runs on the x64 architecture, then you should get the *x64* installer. If your computer runs on the Arm architecture, then you should get the *arm64* installer. If you're not sure, then you most likely need the *x64* installer.

After installing the app, the installer will start the settings app. On the first start-up the settings app will configure the service to run when you log into the system.

When the settings app starts up you can configure the character mappings (you can read more about it in the next article) and other preferences. Start the app using the *Start* button at the bottom of the window. That's it! Now you're ready to use the Keyboard Switch service.

### Uninstalling the App

You can uninstall the app using Windows settings just like you would uninstall any other app.

The uninstaller will not delete the app's configuration. If you want to delete it, then go to your local app data folder, and delete the *KeyboardSwitch* folder.

The uninstaller will also not delete the registry entry which says that your app should start when you log in. If you want to keep your registry clean, you have to disable it in the settings app before uninstalling it.

### Using the Portable Version

If you don't want to install the app (or can't), you can use the portable version of the app. It's literally the same as the installable version; there are no differences. Again, go to the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases) and download *KeyboardSwitch-4.4.0-x64-win.zip* or *KeyboardSwitch-4.4.0-arm64-win.zip*. If you're not sure which one you should download, then it's most probably *x64*. Extract the archive to anywhere you want and start *KeyboardSwitchSettings.exe*. It will configure the app to run when you log in just like the installed version. The configuration for the portable version is also stored under your local app data folder.

## macOS

### Installing the App

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.pkg* file and run it to install the app. If your computer runs on an Apple CPU (e.g. M1), then you should get the *arm64* package. If your computer runs on an Intel CPU, then you should get the *x86\_64* package.

The installer will install multiple things:

* The Keyboard Switch Service app will be put into the */Library/Application Support* folder – you shouldn't run or interact with this app directly.
* The Keyboard Switch Settings app will be put into the */Applications* folder.
* The descriptor file for running the service app when you log in will be put into the */Library/LaunchAgents* folder.

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

Immediately upon opening the app, a dialog window should appear which says that Keyboard Switch would like to control this computer using accessibility features. The app needs this to listen to the magic key combination while running in the background, and without these permissions it won't work. This dialog will appear only when you're installing the app for the first time. If you have installed it previously, then macOS will most probably remember that you gave the app appropriate permissions.

Click the *Open System Preferences* button on the dialog window. Enable the *Keyboard Switch* item. Close System Preferences and go back to the Keyboard Switch Settings app.

If the dialog window didn't appear for some reason, then press the *Start* button at the bottom of the window. The service app will start and immediately stop, because it doesn't have the accessibility permissions, and the dialog window will appear again.

You can configure the character mappings (you can read more about it in the next article) and other preferences. Start the app using the *Start* button. That's it! Now you're ready to use the Keyboard Switch service.

### Uninstalling the App

Many apps on macOS can be uninstalled just by deleting the app bundle from the */Applications* folder. This is not the case with Keyboard Switch. Multiple things should be done to remove it from the system. You shouldn't concern yourself with those things though – you should just run an uninstaller package, and it will remove Keyboard Switch.

As with the installer package, you can also get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download and run the *KeyboardSwitchUninstaller-4.4.0.pkg* file, and Keyboard Switch will be removed.

If you want to delete the app's configuration as well, then delete the *\[home]/Library/Application Support/Keyboard Switch* folder. You can also delete the app's log files by deleting the *\[home]/Library/Logs/Keyboard Switch* folder.

## Linux

### Installing the App

#### Prerequisites

There are several prerequisites for running the app on Linux:

* X11 or Wayland though the latter is supported only on GNOME and KDE Plasma.
* X Keyboard Extension (XKB) which is available by default on both X11 and Wayland.
* libxkbcommon which is usually installed by default.
* The `acl` package which is usually installed by default.
* [wl-clipboard](https://github.com/bugaevc/wl-clipboard) (Wayand only) – used to copy and paste text on Wayland.
* [xsel](https://github.com/kfish/xsel) (X11 only, optional) – used to copy and paste text on X11 if the corresponding setting is enabled.
* Freedesktop conventions – used to make the service app start when you log in, and to make the settings app appear in the list of your installed apps (not required for the app itself though).

The most popular desktop systems (at least GNOME, KDE Plasma, Cinnamon, LXQt, and Xfce) all adhere to the Freedesktop protocols, so the last prerequisite is automatically available, unless you're running a very unusual setup.

Starting with version 4.2, Keyboard Switch uses native clipboard integration on X11 by default. This works well on newer desktop environments but doesn't work well on older versions. If you notice that Keyboard Switch doesn't work well on your system, then you can switch to using xsel instead. xsel must be installed manually though, and the service app must be restarted when this setting is changed. On Wayland, there is no native clipboard integration, the application always uses wl-clipboard.

Keyboard Switch requires access to the input system of Linux. To avoid running it as `root` or giving this access to all applications of the current user, Keyboard Switch creates a separate system group - `keyboard-switch` - during installation. It also installs a udev rule to give access to the input system to this group. The Keyboard Switch executable runs under this group to have this access.

[Click here](https://github.com/TolikPylypchuk/KeyboardSwitch/issues/129) to see the list of Linux distributions on which the app was tested.

{% hint style="warning" %}
If your desktop environment is GNOME, then you should restart it before opening Keyboard Switch Settings. If you're not sure which desktop environment you're using then it's most probably GNOME since it's the default one on Ubuntu, Debian, Rocky, Fedora and others (but not Linux Mint). If you're using X11, Press <kbd>Alt</kbd>+<kbd>F2</kbd>, then type <kbd>r</kbd> and press <kbd>Enter</kbd> – this will restart GNOME. If you're using Wayland (which is most probably the case on newer versions of GNOME), then you'll have to log out and log back in.
{% endhint %}

#### Using a Deb Package

If you're running a Debian-based distribution (e.g., Ubuntu or Mint), then you can install Keyboard Switch using a deb package. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

The package has the following dependencies:

* `acl`
* `libxkbcommon0`
* `wl-clipboard` (as a recommended dependency, installed by default)
* `xsel` (as an optional dependency, not installed by default)

After installation, the settings app will be available in the list of installed apps, and the service app will be configured to run at login.

Both the *amd64* and *arm64* versions are available.

#### Using an RPM Package

If you're running a RHEL-based distribution (e.g., Rocky Linux or Fedora), or SUSE, then you can install Keyboard Switch using an RPM package. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

The package has the following dependencies:

* `acl`&#x20;
* `libxkbcommon.so.0()(64bit)` (libxkbcommon is provided by different packages on RHEL-based distros and SUSE, so this form takes care of both package names)
* `wl-clipboard` (as a recommended dependency, installed by default)
* `xsel` (as a suggested dependency, not installed by default)

After installation, the settings app will be available in the list of installed apps, and the service app will be configured to run at login.

Both the *x86\_64* and *aarch64* versions are available.

#### Using a Tar Archive

Keyboard Switch is also available as a *tar.gz* file. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). You can then extract it to anywhere you like (e.g., into the */opt* directory). The deployed app includes two scripts – *install.sh* and *uninstall.sh*.

*install.sh* does the following:

* creates the `keyboard-switch` system group and grants it access to the input system via a udev rule if the group doesn't exist;
* sets the Keyboard Switch executable to belong to that group so that it has access the input system;
* adds the settings app to the list of installed apps.

The first two items require a one-time root access. Do not run *install.sh* with `sudo` - it will run the needed commands with `sudo` itself which will only require that you enter a password.

*uninstall.sh* removes the app from the list of installed apps.

Apart from the one-time setup of the input system access for Keyboard Switch, these scripts make changes only for the current user.

Both the *x64* and *arm64* versions are available.

The following scripts assume that the */opt* directory is writable. Substitute *x64* with *arm64* if needed.

Here are the steps required for installing the app on Debian, Ubuntu, Linux Mint, etc.:

```bash
sudo apt update
sudo apt install wl-clipboard # Install wl-clipboard which is required on Wayland
sudo apt install xsel # Optional, install only if you plan to use the xsel setting on X11
tar -xzf keyboard-switch-4.4.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
# Enter your password when the sudo prompt appears
```

Here are the steps required for installing the app on RHEL, Fedora, or Rocky Linux:

```bash
sudo dnf install wl-clipboard # Install wl-clipboard which is required on Wayland
sudo dnf install xsel # Optional, install only if you plan to use the xsel setting on X11
tar -xzf keyboard-switch-4.4.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
# Enter your password when the sudo prompt appears
```

Here are the steps required for installing the app on SUSE:

```bash
sudo zypper install wl-clipboard # Install wl-clipboard which is required on Wayland
sudo zypper install xsel # Optional, install only if you plan to use the xsel setting on X11
tar -xzf keyboard-switch-4.4.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
# Enter your password when the sudo prompt appears
```

Here are the steps required for installing the app on Arch Linux:

```bash
sudo pacman -S wl-clipboard # Install wl-clipboard which is required on Wayland
sudo pacman -S xsel # Optional, install only if you plan to use the xsel setting on X11
tar -xzf keyboard-switch-4.4.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
# Enter your password when the sudo prompt appears
```

### Uninstalling the App

For the deb and RPM packages, it's simple – just uninstall the package. For the *tar.gz* file, run the included *uninstall.sh* script, and delete the app's directory.

If you want to delete the app's configuration as well, then there are several ways to do that:

* For deb packages, you can run `apt remove` with the `--purge` option.
* For *tar.gz* files, you can run `uninstall.sh` with the `--purge` option.
* You can delete the *\~/.config/keyboard-switch* directory manually.

There is no way to delete the app configuration automatically for RPM packages.

The `keyboard-switch` group is not removed automatically. If you want to remove this group and its accesses as well, run the following commands:

```bash
sudo rm /etc/udev/rules.d/99-keyboard-switch.rules
udevadm control --reload-rules
sudo groupdel keyboard-switch
```


# The Settings App

Keyboard Switch Settings is a simple app which controls the behavior of the Keyboard Switch service. You can find the app in the list of your installed apps (e.g. the Start menu on Windows). Here's how it looks:

<figure><picture><source srcset="/files/Z4l3QJojGsNjTYzDvomm" media="(prefers-color-scheme: dark)"><img src="https://content.gitbook.com/content/lbY7ecZfDzM6g3TgEUhf/blobs/SCeOvCMADfUkWo1sut8c/v4.3-screen-preferences.png" alt="The Keyboard Switch Settings app"></picture><figcaption><p>The Keyboard Switch Settings app</p></figcaption></figure>

The app is composed of four tabs:

* Character mappings: contains the settings which tell Keyboard Switch how to transform characters between layouts
* Preferences: contains other settings
* Sandbox: lets you play around with switching text
* About: contains info about the app

At the bottom there's a strip with the status of the Keyboard Switch service. If it's not running, you can press the *Start* button to start it manually (although usually you wouldn't do that because the service will start when you log in). If the service is running, you can stop it by pressing the *Stop* button. It won't actually kill it – it will send a *stop* command, and the service will do some clean-up and stop on its own. If it's taking a long time to stop, it may mean that something went wrong. In that case you can force it to stop by pressing the *Kill* button.

{% hint style="info" %}
If you change anything in the settings app, you can save it or cancel it. When you save it, the settings app sends a notification to the service app (if it's running) about changes in configuration, so you don't have to restart the service after saving.
{% endhint %}

The following articles describe each tab of the settings app in more detail.


# Preferences

The Preferences tab contains other settings which control the behavior of the Keyboard Switch service. Here's how it looks:

<figure><picture><source srcset="/files/Z4l3QJojGsNjTYzDvomm" media="(prefers-color-scheme: dark)"><img src="https://content.gitbook.com/content/lbY7ecZfDzM6g3TgEUhf/blobs/SCeOvCMADfUkWo1sut8c/v4.3-screen-preferences.png" alt="The preferences tab"></picture><figcaption><p>The preferences tab</p></figcaption></figure>

Following is the discussion on the many fields that are in this tab.

## Checkboxes

There are four checkboxes (five on Linux) at the top of the Preferences tab:

* Instant switching
* Switch layouts
* Start the service when you log in
* Show a message about uninstalled layouts
* Use xsel for clipboard integration (only on Linux)

The first checkbox controls whether the Keyboard Switch service should use instant switching or not. The default is yes. The service app needs to access the text to transform it, and for that it uses the clipboard. When instant switching is enabled, the service app will simulate pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> (or <kbd>Command</kbd>+<kbd>C</kbd> on macOS) to copy text into the clipboard. This is why you must first select the text before you let the service app switch it. After transforming the text, the service app will put it back into the clipboard and if the instant switching mode is enabled, it will simulate pressing <kbd>Ctrl</kbd>+<kbd>V</kbd> (or <kbd>Command</kbd>+<kbd>V</kbd> on macOS) to paste the new text instead of the selected text. If you disable this mode, you will have to manually copy the text before switching and then paste it afterwards. In addition, when this mode is enabled, the app will try to preserve the text that was in clipboard previously and restore it after switching (if the clipboard didn't contain text before switching, e.g., a file or a picture, it won't be restored).

The second checkbox controls whether the service app should switch the layout for you after transforming the text. The default is yes, and there's probably no reason to ever disable it. It just reduces the number of actions you have to do in order to get back on track with typing the text.

The third checkbox lets you control whether the service app will start when you log in. When you open the settings app for the first time, it configures the service app to run at startup automatically.

The fourth checkbox controls whether the settings app should show a warning about uninstalled layouts. If you install a new layout in the system, you should open the settings app and configure it in the Character Mappings tab. If you uninstall a layout, its configuration will still be saved in the app's settings, but it will essentially be redundant – the layout is not present in the system anymore and hence the service app won't need its configuration. When you uninstall a layout and open the settings app, it will show you a warning and a button to delete the unused configuration. If you want to ignore this warning for whatever reason, then uncheck this checkbox.

The fifth checkbox (which is only available on Linux) controls whether the clipboard integration is implemented directly through X11, or through xsel. Direct integration is the default, but may not work well on older desktop environments. If it doesn't, then xsel should be used instead. Unlike other options, changing this one requires restarting the service app. xsel must be installed manually for this option to work.

## Switch Settings

You can switch text just by pressing modifier keys. This is similar to switching keyboard layouts in Windows itself – the default key combination to switch layouts in Windows is <kbd>Alt</kbd>+<kbd>Shift</kbd>. You can control which key combination to press to switch text and how many times. The setting contains four fields:

* Modifier keys for switching forward
* Modifier keys for switching backward
* Press count
* Wait time (in milliseconds)

You can select <kbd>Ctrl</kbd>, <kbd>Alt</kbd>/<kbd>Option</kbd>, <kbd>Shift</kbd>*,* and <kbd>Win</kbd> (also known as <kbd>Super</kbd>, <kbd>Meta</kbd>, or <kbd>Command</kbd>), or their combination as modifier keys for switching. The default is <kbd>Ctrl</kbd>+<kbd>Shift</kbd> to switch forward, and <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> (<kbd>Ctrl</kbd>+<kbd>Option</kbd>+<kbd>Shift</kbd> on macOS) to switch backward.

You can also control how many times you should press those modifier keys to switch the text. The default is 2. Max value for this field is 10, but even that is way too much. Min value is 1, but be careful if you set it to 1, because then it would be easy to press it by accident.

Wait time controls how much time the service app waits before deciding that you're not intending on switching text. For example, let's say that the press count is 3, and wait time is 400 ms (which is the default value). You press the key combination. The app then waits for 400 ms to see whether you will press the key combination again. If you don't, then it realizes that you don't want to switch text. If you press the key combination again within this time, the app will then wait again for 400 ms. You then press the key combination for the third time, and the app realizes that you want to switch the text. The min value for this field is 100 ms (which usually makes the app give up waiting much too fast), and the max value for this field is 1000 ms (so, 1 full second, which is usually too slow). 400 ms is the sweet spot, but maybe it won't be for you. You should play around with this setting to figure out which value works best for you.

{% hint style="info" %}
Wait time is ignored if the press count is set to 1.
{% endhint %}

## Theme Settings

The way the settings app looks can be configured using the *App theme* and *Variant* dropdowns.

Three themes are supported:

* Fluent – this theme uses Fluent Design v2 and is the default one on Windows. The screenshots in these docs show the Fluent theme.
* macOS – this theme uses the default macOS look and feel and is the default one on macOS.
* Simple – this theme uses simple styles and is the default one on Linux.

Three variants are supported:

* Light
* Dark
* System – light or dark depending on system settings. This variant is the default one.


# Character Mappings

In order for the Keyboard Switch service to know how to map characters, ideally, you have to configure the character mappings yourself. The app reads the list of installed layouts in the system, so it knows which layouts you use and in what order. What it doesn't (and can't) know is the physical layout of your keyboard, so it doesn't know what happens if you press certain keys on your keyboard. Although it can auto-configure the mappings, and it will usually work well, there may be cases when it doesn't work well.

<figure><picture><source srcset="/files/JQ2PmzYjvIRuok3sOTWx" media="(prefers-color-scheme: dark)"><img src="https://content.gitbook.com/content/lbY7ecZfDzM6g3TgEUhf/blobs/wwas53MUK6iOXLg3ompR/v4.3-screen-char-mappings.png" alt="The character mappings tab"></picture><figcaption><p>The character mappings tab</p></figcaption></figure>

## Text vs Keyboard

This section explains *why* you need to configure character mappings for the app. If you're not interested, feel free to skip it.

Working with text and working with keyboard are two wildly different things. You, the user of a computer, usually work with a keyboard (or other input devices, but those don't matter here). This app however works with text (even though its name might suggest differently), and so text transformation during switching will most probably not be perfect.

Ideally you wouldn't have to configure the app at all – it would just know how to transform the text you mistyped into another layout. After all, the OS somehow knows which characters to produce when you press various keys! But going that way would be extremely difficult, if not impossible.

Firstly, pressing keys and entering characters are absolutely not the same thing. Many keys don't have corresponding characters at all, like <kbd>Ctrl</kbd> or <kbd>Page Up</kbd>. The same key press can produce different characters based on the state of other keys. For example, the <kbd>A</kbd> key usually produces **a**, but when <kbd>Shift</kbd> is down, the key produces **A**. And then there are dead keys – key combinations that produce one character by pressing two (or even three) keys. For example, in the US International layout, pressing <kbd>'</kbd> and then <kbd>A</kbd> will produce **á**.

Secondly, it's impossible to know which keys have been pressed just by looking at text. This is because the same character can be produced using different keys or key combinations (or it can be pasted, so the keyboard wouldn't be used at all).

So, in order to just know how to transform the text you've mistyped, the app would have to keep track of the keys you've pressed and then infer which of those pressed keys actually played a role in producing the mistyped text and then ask the OS which characters would be produced with the same key sequence. You can see how that's unreasonable. First of all, the app would have to track *all* the keys you press, and that would be quite sketchy. Would you trust an app which logs everything you type? I certainly wouldn't. And ethics aside, there still are technical issues. How many keys should the app track? What happens if the user pastes part of the text instead of typing it? Etc., etc.

And that's why the app uses a much simpler solution – it lets you, the user, figure out how the text should be transformed. The app can auto-configure the mappings using a simple method, but it's still up to you to check whether it's all correct.

## How Character Mappings Work

Here's how the tab looks if the configuration is empty:

<figure><picture><source srcset="/files/cIQc9s6kqo5offfdDeHz" media="(prefers-color-scheme: dark)"><img src="https://content.gitbook.com/content/lbY7ecZfDzM6g3TgEUhf/blobs/grRyFYYWoMON4KdZD4ml/v4.3-screen-char-mappings-empty.png" alt="The character mapping tab when the configuration is empty"></picture><figcaption><p>The character mappings tab when the configuration is empty</p></figcaption></figure>

You have to enter every character you can think of (which can be entered using your keyboard) into the text fields which correspond to layouts. For example, press the <kbd>Q</kbd> key, then press the <kbd>W</kbd> key, and so on. Then press <kbd>Shift</kbd>+<kbd>Q</kbd>, then <kbd>Shift</kbd>+<kbd>W</kbd> etc. to add uppercase letters.

You should press the keys *in the same order* for all layouts. Order matters here because the service will look at characters in same positions to determine how to transform the text. For example, let's say you have two layouts in your system: English (US) and Ukrainian (Enhanced). You put **q** as the first character in the text field for English, and **й** as the first character in the text field for Ukrainian (because that's the character you get when you press the <kbd>Q</kbd> key). Now the service will know that when it switches from English to Ukrainian, it should transform **q** to **й**. If the second characters are **w** and **ц** for English and Ukrainian respectively, then the service will transform **w** to **ц**.

If you don't want to map a certain character, you can put a space in its position in the other layout. The space character acts as a *don't map this character* command, though it should generally be avoided.

{% hint style="info" %}
This app is "Western-oriented". I developed it specifically to handle switching between Cyrillic and Latin scripts. I don't know how it will work (if at all) with Eastern languages/scripts.
{% endhint %}

## Auto-Configuration

Even though you have to do it only once, configuring character mappings is still cumbersome and error prone. That's why the app includes the auto-configuration feature. It's available only when all text fields are empty. The auto-configuration is quite simple (naïve even), and it shouldn't be 100% trusted, so you still have to check its output and fix mistakes or add other characters manually. But usually auto-configuration should be good enough.

Auto-configuration is available only when the character mapping configuration is completely empty.

{% hint style="info" %}
The character mappings are auto-configured automatically when the settings app is opened for the first time.
{% endhint %}

Here's how the tab looks after running auto-configuration:

<figure><picture><source srcset="/files/aS7C5BbJokSruW17hibm" media="(prefers-color-scheme: dark)"><img src="https://content.gitbook.com/content/lbY7ecZfDzM6g3TgEUhf/blobs/uGXwzMpUeUnGTPKlbgjT/v4.3-screen-auto-configuration.png" alt="The character mapping tab after auto-configuration"></picture><figcaption><p>The character mappings tab after auto-configuration</p></figcaption></figure>

### Windows and macOS

What auto-configuration does on Windows and macOS is basically ask the OS what would happen if certain keys were pressed using various layouts. There is no easy way to get the information about *all* keys on your keyboard, so it asks only about the most common ones. Here's the list of those keys for the US layout:

* All letter keys (<kbd>Q</kbd>, <kbd>W</kbd>, <kbd>E</kbd> etc.)
* Number keys
* Other common keys: <kbd>\[</kbd>, <kbd>]</kbd>, <kbd>;</kbd>, <kbd>'</kbd>, <kbd>,</kbd>, <kbd>.</kbd>, <kbd>/</kbd>, <kbd>\\</kbd>, <kbd>-</kbd>, <kbd>=</kbd>, and <kbd>\`</kbd>
* All those keys with the <kbd>Shift</kbd> key
* All those keys with the <kbd>AltGr</kbd>/<kbd>Option</kbd> key
* All those keys with the <kbd>Shift</kbd>+<kbd>AltGr</kbd>/<kbd>Option</kbd> keys

Not all of those key combinations actually produce characters for all layouts. So, after asking the OS about all of these keys, the app keeps only those character combinations which are defined for all layouts. For example, on Windows if you press <kbd>AltGr</kbd>+<kbd>U</kbd> in the Ukrainian layout, you will get **ґ**, but if you press those keys in the US layout, you won't get anything at all, so the app will just throw **ґ** out as it won't know how to map it to the US layout.

### Linux

Unlike Windows and macOS, there's actually a way to ask the OS (though X11) which characters are produced by all possible key presses. What the app will do is ask about characters produced by all key codes on all shift levels (there are 64 of them!). As with Windows, it will keep only those combinations which are defined for all layouts.

## Limitations

You can map every character only once per layout. Otherwise, it would be impossible to map characters deterministically.

Characters are always mapped one to one. You cannot map one character to several characters.

Dead keys are not supported.

The space character cannot be mapped to other characters. This is not really a limitation, because the space character is the same in every layout (at least that's the assumption).

The app doesn't play nicely with text if you switched the layout yourself in the middle of typing. If that's the case, the app will not switch it correctly, and you will have to fix some of it yourself.


# Other Tabs

Other tabs in the settings app include the Sandbox tab and the About tab.

## Sandbox

Sandbox is absurdly simple – it's just a text box. That's it! Here's how it looks:

<figure><picture><source srcset="/files/5td1JBwwJUYGGuDcDFG0" media="(prefers-color-scheme: dark)"><img src="https://content.gitbook.com/content/lbY7ecZfDzM6g3TgEUhf/blobs/fDboHupAMZ6pF6EFV406/v4.3-screen-sandbox.png" alt="The sandbox tab"></picture><figcaption><p>The sandbox tab</p></figcaption></figure>

Sandbox lets you play around with switching text when you change the app's settings. It contains no logic whatsoever. It's literally just a text box.

## About

The About tab contains some general info about the app. Here's how it looks:

<figure><picture><source srcset="/files/iekvV5puyT0aKJqroD80" media="(prefers-color-scheme: dark)"><img src="https://content.gitbook.com/content/lbY7ecZfDzM6g3TgEUhf/blobs/QeY2XHHrrzc5EGFVMnoo/v4.3-screen-about.png" alt="The about tab"></picture><figcaption><p>The about tab</p></figcaption></figure>

If you want more info, you can view the docs (these very pages).

You can also check whether updates for the app are available. If they are indeed available, then you can go to the releases page on GitHub to get them. The app doesn't support auto-updating, so you will have to install a newer version yourself. Remember that you should stop the service app before installing a newer version.

That's it for the settings app. If you want technical info about Keyboard Switch, you can check out the next articles.


# Command Line Interface

The Keyboard Switch service app has a CLI which you can use to control it. On Windows, it's not really convenient as GUI apps cannot output anything to the console, but it can be used as well.

The name of the executable is `KeyboardSwitch`. This article will assume it's installed on Linux in the `/opt/keyboard-switch` directory. On macOS, it's located in the `/Library/Application Support/Keyboard Switch.app/Contents/MacOS` directory.

## Commands

### Running the App

To start Keyboard Switch, simply run it in the terminal:

```
/opt/keyboard-switch/KeyboardSwitch &
```

The `&` makes the service app run in the background. On Windows, the `&` is not needed as GUI apps always run separately from the terminal.

Keyboard Switch is a single-instance app. If one instance is already running, and you start another one, it will immediately silently exit.

The app will exit immediately if it cannot find the settings file. This file is created when you run the settings app for the first time. This is done so that there's a lower chance that this app will run in an unconfigured state.

### Stopping the App

To stop Keyboard Switch, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --stop
```

If an instance of Keyboard Switch is running, this command will stop it. If no instance is running, it will do nothing.

### Reloading the Settings

To reload the settings of Keyboard Switch, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --reload-settings
```

If an instance of Keyboard Switch is running, this command will make it invalidate its current settings and reload them. If no instance is running, it will do nothing.

### Checking Whether the App Is Running

To check whether Keyboard Switch is running, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --check
```

If an instance of Keyboard Switch is running, this command will output `KeyboardSwitch is running`. Otherwise, it will output `KeyboardSwitch is not running`.

### Showing a Help Message

To show the help message, run either of the following:

```
/opt/keyboard-switch/KeyboardSwitch --help
/opt/keyboard-switch/KeyboardSwitch -?
```

### Command Formats

The aforementioned commands can be prefixed with `--`, `-`, or `/`. For example, to stop Keyboard Switch, you can specify `stop`, `-stop`, `--stop`, or `/stop`.

## Exit Codes

The following exit codes are available:

* `0` – The app has exited successfully.
* `1` – An unspecified error has occurred.
* `2` – The app cannot run, because its settings have an incompatible version. The app is backward-compatible with respect to settings versions – it will read the settings created by an older version and modify them to fit the current version. But it's not forward-compatible – version 4.3 will not work if the settings were created or updated by a newer version.
* `3` – `stop`, `reload-settings`, or `check` was specified as the command, but no instance of KeyboardSwitch is running.
* `4` – An invalid command was specified.
* `5` – The settings file was not found.
* `6` – The app doesn't have access to the accessibility API on macOS.


# Technical Stuff

Keyboard Switch is written using [C#](https://github.com/dotnet/csharplang) and [.NET 9](https://dotnet.microsoft.com/en-us/download/dotnet/8.0). Following is the list of technologies used in this app and some other technical aspects.

## UI

The Keyboard Switch Settings app is written using [Avalonia](https://avaloniaui.net), a cross-platform UI framework for .NET. I chose it because unlike other UI frameworks for .NET, it's cross-platform, and I had to do literally nothing for it to work on macOS and Linux as well. The styles are provided by [FluentAvalonia](https://github.com/amwx/FluentAvalonia), the [Devolutions macOS theme](https://github.com/Devolutions/avalonia-extensions), and Avalonia's simple theme.

Previous versions of the app used .NET Framework and WPF. Back then I didn't expect to have it working on different platforms.

Previous versions of the app also included a tray icon so you could see that the app is running. I removed it in version 3.0 as I don't see much value in keeping it and cluttering your tray.

## Core Logic

### Windows

The service app is just an app which runs in the background. I could have made it into a Windows service but decided against it when I read somewhere that Windows services cannot set up keyboard hooks. I didn't actually verify this info, so I'm not sure it's correct, but the background app approach works just fine, so it's likely to stay this way.

The service app calls various native functions from the Windows' *user32.dll*. It uses [Vanara](https://github.com/dahall/Vanara) to call them.

In the previous versions (up to 3.0) the service and the settings app were not separated. It was just an app running with a hidden window which showed up when you opened it. Having a hidden window always loaded is not that great of an idea, even though it used very little RAM.

### macOS

On macOS, the service app runs as a *launchd* service. *launchd* provides the ability to start at login. The settings app starts the service app through *launchd* as well.

macOS 10.15+ is required since it's the oldest version still supported by .NET.

The service app uses multiple native macOS frameworks:

* *CoreFoundation* – for low-level string, array, and pointer manipulation.
* *CarbonCore* (part of *CoreFoundation*) – for translating key codes with layout info into Unicode characters.
* *CoreGraphics* – for simulating keyboard events.
* *HIToolbox* – for working with keyboard layouts.
* *AppKit* – for working with the clipboard.

### Linux

At first, I decided to run the app as a *systemd* service, but it proved not to provide much value, so I've since reverted this decision.

The service app uses X11, especially the X Keyboard Extension, and the X Test Extension. Currently it doesn't work on Wayland, even through XWayland. It calls various native Xlib functions using P/Invoke directly.

The app interacts directly with X11 for clipboard integration – the code for this integration is based on code from Avalonia. It can also use [xsel](https://github.com/kfish/xsel) for clipboard integration instead.

If the Linux desktop environment is GNOME, then the app switches layouts a little differently than in other desktop environments. GNOME doesn't let apps switch layouts using X11 directly – it will immediately switch it back. Instead, the settings app adds a small GNOME Shell extension (which is simply called Switch Layout) and the app switches layouts through it. GNOME should be made aware of this extension after installation; hence you should restart it after starting the settings app. If you don't then the app will still work but won't be able to switch layouts until you log out or reboot.

### The Settings App

The core logic of the settings app is implemented using [ReactiveUI](https://www.reactiveui.net) as the MVVM framework. Also, [Splat](https://github.com/reactiveui/splat) is used for service location.

## App Structure

Keyboard Switch and Keyboard Switch Settings are published as self-contained single-file applications. The size difference between single-file applications and standard applications with shared libraries is negligible since single-file applications can be compressed.

On macOS, the two applications are located in separate directories – this is done because on macOS every application should be contained inside a bundle.

## The Global Keyboard Hook

The app uses [libuiohook](https://github.com/kwhat/libuiohook) to create a global keyboard hook. The library is cross-platform and supports almost all popular OSes and architectures. Since this library is native and it's non-trivial to build, I've developed a .NET wrapper for it, [SharpHook](https://github.com/TolikPylypchuk/SharpHook), so that I don't have to deal with a native library in this project.

Previously, the app used a Windows keyboard hook directly, but that doesn't work on other systems.

## Preferences

Preferences are stored in the user's local app data folder (under the *Keyboard Switch* directory) on Windows. I didn't put it into the normal app data folder because that one is shared if you use the same Windows account on multiple machines, and that kind of defeats the purpose of this app being configured for each machine individually.

On macOS, the settings are stored in the *\~/Library/Application Support/Keyboard Switch* directory.

On Linux, the settings are stored in the *\~/.config/keyboard-switch* directory.

This app stores settings as plain JSON files.

## Logging

This app uses a plain-text log file to log the stuff it’s doing and errors it encounters along the way. [Serilog](https://serilog.net) is used as the logging library.

On Windows and Linux, the log file is stored in the same folder as the preferences, and on macOS, it's stored in the *\~/Library/Logs/Keyboard Switch* directory. The log file is rolled over after reaching 10 MB.

If you really want to (and know how), you can change the logging configuration in the *appsettings.json* file. On Windows and Linux, this file is located in the same folder as the app itself. On macOS, this file is located in the bundle's resources folder, and you probably shouldn't change it as it may break the bundle's signature (though I'm not sure about that).

## Tests

There are very few tests and only for the core functionality. Honestly, I don't even know how to test the rest, because the rest of the app is essentially creating system-wide side effects, so don't think it's really testable. As for the settings app, well, I could test it, but that would take a lot of time, and the app is pretty simple, so I don't plan on doing it in the nearest future.

## Docs

The docs are built and hosted on [GitBook](https://www.gitbook.com).

Previously these articles were built using [Jekyll](https://jekyllrb.com) and hosted on [GitHub Pages](https://pages.github.com), and used the [Minimal Mistakes theme](https://mmistakes.github.io/minimal-mistakes).

## Installers

[WiX Toolset 6.0](https://www.firegiant.com/wixtoolset) is used to create the Windows installer. Previously, [WixSharp](https://github.com/oleg-shilo/wixsharp) was used, but the installer is really simple, so there is no need for it. Also, WixSharp requires .NET Framework, while WiX 4.0+ doesn't require it anymore.

The installer package for macOS is created using the default macOS tools.

The deb and RPM installers for Linux are also created using the default CLI tools.

## Building from Source

You can build Keyboard Switch from source if you like. All projects require .NET 8.

### The Projects

The app consists of 10 projects grouped into 3 folders:

* src:
  * *KeyboardSwitch*: The Keyboard Switch service itself
  * *KeyboardSwitch.Core*: Core functionality and interfaces for all projects
  * *KeyboardSwitch.Settings*: The Keyboard Switch Settings app
  * *KeyboardSwitch.Settings.Core*: The core logic of the settings app
  * *KeyboardSwitch.Windows*: The implementation of the core functionality for the Windows platform
  * *KeyboardSwitch.MacOS*: The implementation of the core functionality for the macOS platform
  * *KeyboardSwitch.Linux*: The implementation of the core functionality for the Linux platform
* test:
  * *KeyboardSwitch.Test*: The unit test project
* build:
  * *KeyboardSwitch.Build*: The NUKE project for building Keyboard Switch
  * *KeyboardSwitch.Windows.Installer*: The WiX installer project

### Building the App Itself

Keyboard Switch uses [NUKE](https://nuke.build) as its build system. It's not required to build Keyboard Switch, but it greatly simplifies creating the target artifacts. You should call the `./build.cmd` script from the root folder to run NUKE (the script is cross-platform).

The following targets are available (the default target is `Compile`):

* `Restore` – runs `dotnet restore` for all projects.
* `Clean` – runs `dotnet clean` for all projects.
* `Compile` – runs `dotnet build` for all projects.
* `Test` – runs `dotnet test` for the test project.
* `Publish` – runs `dotnet publish` for the *KeyboardSwitch* and *KeyboardSwitch.Settings* projects.
* `CreateZipArchive` – creates a *zip* archive which contains a portable distribution of Keyboard Switch.
* `CreateTarArchive` – creates a *tar.gz* archive which contains a portable distribution of Keyboard Switch.
* `CreateWindowsInstaller` – creates a Windows installer.
* `PrepareMacOSPackage` – prepares all files required for a macOS package.
* `CreateMacOSPackage` – creates a macOS package.
* `PrepareMacOSUninstallerPackage` – prepares all files required for a macOS uninstaller package.
* `CreateMacOSUninstallerPackage` – creates a macOS uninstaller package.
* `PrepareDebianPackage` – prepares all files required for a deb package.
* `CreateDebianPackage` – creates a deb package.
* `PrepareRpmPackage` – prepares all files required for an RPM package.
* `CreateRpmPackage` – creates an RPM package.

The Windows installer can be created on any OS. The macOS packages can only be created on macOS and require an Apple Developer account and certificates. The deb and RPM packages can only be created on Linux.

The following parameters are available:

* `Configuration` – `Debug` or `Release`. All targets except `Restore`, `Clean`, `Compile`, and `Test` require `Release` which is the default.
* `TargetOS` – `Windows`, `macOS`, or `Linux`. The currently running OS is the default. Windows installer requires `Windows`. macOS packages require `macOS`. Linux packages require `Linux`.
* `Platform` – `x64` or `arm64`. The currently running platform is the default.
* `PublishSingleFile` – `true` or `false`. All targets after `Publish` require `true`.
* `OutputFileSuffix` – the suffix to use on output files before the extension. For example, portable Windows distributions use the `win` suffix.

The following parameters are available for building macOS packages:

* `AppleId` – your Apple developer ID.
* `AppleTeamId` – your Apple team ID.
* `AppleApplicationCertificate` – the ID of your Apple application certificate.
* `AppleInstallerCertificate` – the ID of your Apple installer certificate.
* `NotaryToolKeychainProfile` – the Keychain profile to be used by `notarytool` when notarizing the package.

There are more parameters available for macOS, but they are only used when running in GitHub Actions. Certificates must be stored in Keychain for macOS packages to be built.

Here is the NUKE execution plan which shows the dependencies between targets:

<figure><img src="https://content.gitbook.com/content/lbY7ecZfDzM6g3TgEUhf/blobs/ZnSRvj722v4UrF8ci6Rk/v4.3-nuke-execution-plan.png" alt="NUKE execution plan"><figcaption><p>NUKE execution plan</p></figcaption></figure>


# About

Keyboard Switch. Version 4.3.1. Created by [Tolik Pylypchuk](https://github.com/TolikPylypchuk).

## Acknowledgements

The UI for the settings app was created using [Avalonia](https://avaloniaui.net) with [ReactiveUI](https://www.reactiveui.net), [FluentAvalonia](https://github.com/amwx/FluentAvalonia), and the [Devolutions macOS theme](https://github.com/Devolutions/avalonia-extensions). The global keyboard hook is implemented using [libuiohook](https://github.com/kwhat/libuiohook). Windows installer created with [WiX Toolset](https://wixtoolset.org). Docs are built using [GitBook](https://www.gitbook.com). Icon made by [Smashicons](https://smashicons.com) from [www.flaticon.com](https://www.flaticon.com).

## Changelog

### [v4.3.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.3.1) (July 20, 2025)

* When Keyboard Switch is running on Windows, it doesn't cause some editors to insert random characters when <kbd>Alt</kbd>+<kbd>Arrow</kbd> keys are pressed anymore

### [v4.3.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.3.0) (June 30, 2025)

* The settings app now supports different themes for different OSes
* Dark mode is now available for the settings app
* The preferences tab is now the default tab in the settings app
* The application now works correctly when multiple users are logged in at the same time
* The application doesn't interfere with Alt codes on Windows anymore

### [v4.2.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.2.0) (August 14, 2024)

* Arm64 is now officially supported for Windows and Linux
* The converter has been removed
* A single modifier key can now be configured as the magic key for Keyboard Switch
* The app now integrates with the clipboard directly on Linux, without xsel, but this may not work well on older desktop environments, so integration through xsel is still possible
* The internal format of the settings was changed, so when updating to version 4.2 from older versions, the settings will be reverted to the defaults – you should reconfigure the app if you had custom configuration before
* Windows installer doesn't delete all users' configurations when uninstalling the app anymore
* Purging configuration is now available on Linux for deb packages and the *tar.gz* file
* The settings app now does auto-configuration by itself when being opened for the first time
* Switching layouts now works on GNOME 45+
* The application size and startup time has been reduced
* The application has been upgraded to .NET 8 and Avalonia 11
* WiX Toolset 5.0 is now used for the Windows installer, removing the need for .NET Framework
* NUKE is now used as the build tool

### [v4.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.1) (February 10, 2022)

* The app now works on macOS
* The app now supports Arm64 in addition to x64 (but the support is experimental for Windows and Linux)
* The app now switches layouts using native methods on Linux, hence layout settings are not needed anymore
* On Windows switching backward works correctly when there are more than two layouts
* The settings app will configure the service app to run at login when opened for the first time, instead of installers doing that – this means that the service app will be configured correctly for all users
* Windows Installer can delete all users' configurations when uninstalling the app

This is the first minor release which contains new features instead of just bug fixes, and it's a big one at that.

### [v4.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.0) (November 28, 2021)

* The app now works on Linux (via X11 only; Wayland is not supported)
* The legacy hot-key mode was removed – only the modifier keys mode is available
* The UI theme is overhauled
* The converter is hidden by default
* .NET 6 is used instead of .NET Core 3.1
* The app's performance was improved, though it's still not ideal

This is the first major version of the app which is not completely rewritten, though it was significantly changed. From now on, most changes (like macOS support) will come as minor versions, and version 4 will be the major version for the foreseeable future.

### [v3.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v3.0) (August 4, 2020)

* A completely rewritten app based on .NET Core and working as a truly UI-less app instead of an app with a hidden window
* The settings are now a separate app written with Avalonia instead of WPF
* Tray icon was removed
* Added the ability to switch between multiple layouts of the same language (e.g. QWERTY and Dvorak for English)
* Instant switching mode is not experimental anymore and enabled by default
* Added the ability to auto-configure character mappings
* Added checking for updates

### [v2.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v2.1) (April 1, 2018)

Minor bug fixes

### [v2.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v2.0) (January 13, 2018)

* Brand new installer for the app
* Instant switching mode
* Updated readme
* Updated configuration
* Minor UI updates
* Minor bug fixes

### [v1.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v1.1) (somewhere in 2015)

Minor bug fixes

### v1.0 (somewhere in 2015)

All the basic functionality:

* Switching text
* Starting at system startup
* Tray icon

## License

MIT License

Copyright (c) 2015 Anatoliy Pylypchuk

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


# Keyboard Switch

Welcome to the Keyboard Switch docs!

Keyboard Switch is an application which switches typed text as if it were typed with another keyboard layout.

If you ever write some text and then realize that you have written it using a wrong layout, you don't have to delete it and start over anymore. Just select the text, press a magic key combination, and that's it!

I hope this app will make your life at least 1% easier :)

## Quick Start

### Windows

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.msi* file and run it to install the app. If your computer runs on the x64 architecture, then you should get the *x64* installer. If your computer runs on the Arm architecture, then you should get the *arm64* installer. If you're not sure, then you most likely need the *x64* installer.

After installation, the Keyboard Switch Settings app will start. It may take some time as the app will do some initial setup. If it doesn't start for some reason, then find it in the list of your apps.

In the opened app, press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> twice instead.

### macOS

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.pkg* file and run it to install the app. If your computer runs on an Apple CPU (e.g. M1) then you should get the *arm64* package. If your computer runs on an Intel CPU then you should get the *x86\_64* package.

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

Immediately upon opening the app, a dialog window should appear which says that Keyboard Switch would like to control this computer using accessibility features. The app needs this to listen to the magic key combination while running in the background, and without these permissions it won't work.

Click the *Open System Preferences* button on the dialog window. Enable the *Keyboard Switch* item. Close System Preferences and go back to the Keyboard Switch Settings app.

In the settings app, press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Option</kbd>+<kbd>Shift</kbd> twice instead.

To uninstall Keyboard Switch you should run an uninstaller package. You can also get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

### Linux

The app is available as a deb package (for Debian-based distributions, such as Ubuntu, Mint etc.), an RPM package (for RHEL-based distributions, like Rocky Linux or Fedora, as well as SUSE), and a simple *tar.gz* file. You can get these files from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

{% hint style="info" %}
If you're using an RPM package, there are a couple things to note before installing the app (which you can find in the [installation](/usage-guides/installation#installing-the-app) article).
{% endhint %}

Bear in mind that Keyboard Switch only works on X11 – it won't work on Wayland (even with XWayland).

If you use the deb or RPM package, then simply install it either by double-clicking on it, or through the terminal. If you use the *tar.gz* file, then the set-up is not quite as quick, so you can read about it in the [installation page](/usage-guides/installation#installing-the-app).

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

{% hint style="warning" %}
If your desktop environment is GNOME, then you should restart it right after opening Keyboard Switch Settings. If you're not sure which desktop environment you're using then it's most probably GNOME since it's the default one on Ubuntu, Debian, Rocky, Fedora and others (but not Linux Mint). Press <kbd>Alt</kbd>+<kbd>F2</kbd>, then type <kbd>r</kbd> and press <kbd>Enter</kbd>. This will restart GNOME.
{% endhint %}

In the opened app, press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> twice instead.

## How the App Works

The app is composed of two parts: the Keyboard Switch service application and the Keyboard Switch Settings application. The service always runs in the background (and starts when you log into the system) and listens to key presses. When you press the magic key combination, it reacts by copying the selected text, transforming it, and pasting it for you. The settings app is used for configuring the service and for starting/stopping it manually.

Here are the basic steps you should take to switch the text:

* Type some text using an incorrect layout
* Realize your mistake
* Select the text (you can press <kbd>Ctrl</kbd>+`A` to select all text, or `Command`+<kbd>A</kbd> on macOS)
* Press the magic key combination (the default is pressing <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice)
* Profit

The app uses the list of your layouts in the same order as defined by the system. You can switch both forward and backward through this list. It will look at the current layout to determine how to switch text, so you shouldn't change the layout before switching. The app also automatically changes the layout, so you don't have to do it yourself.

The app uses the clipboard to get the text to transform and then puts the transformed text back into the clipboard. The app will try to preserve the text that was in the clipboard before switching and to restore it afterwards. It doesn't guarantee that the text will be restored though. Also, any non-text data (e.g., a file or a picture) will not be restored.

{% hint style="info" %}
**Note:** The app simulates pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> (or <kbd>Command</kbd>+<kbd>C</kbd> on macOS) to copy and <kbd>Ctrl</kbd>+<kbd>V</kbd> (or <kbd>Command</kbd>+<kbd>V</kbd> on macOS) to paste text. This is the default behavior for most applications. But if you are working in an app which behaves differently on those key presses (e.g., a terminal), this app will not be able to instantly switch text. You can disable this behavior and copy/paste the text manually.
{% endhint %}

## Supported Platforms

Keyboard Switch currently works on Windows 10/11 (version 1607 or later), macOS 10.15 or later, and Linux via X11. As for Linux, it needs several prerequisites to run (more on that on [the installation page](/usage-guides/installation#linux)).

The x64 and Arm64 architectures are both supported.


# Installation

## Windows

### Using a Windows Installer

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.msi* file and run it to install the app. If your computer runs on the x64 architecture, then you should get the *x64* installer. If your computer runs on the Arm architecture, then you should get the *arm64* installer. If you're not sure, then you most likely need the *x64* installer.

After installing the app, the installer will start the settings app. On the first start-up the settings app will configure the service to run when you log into the system.

When the settings app starts up you can configure the character mappings (you can read more about it in the next article) and other preferences. Start the app using the *Start* button at the bottom of the window. That's it! Now you're ready to use the Keyboard Switch service.

### Uninstalling the App

You can uninstall the app using Windows settings just like you would uninstall any other app.

{% hint style="warning" %}
The uninstaller will not delete the app's configuration. If you want to delete it, then go to your local app data folder, and delete the *KeyboardSwitch* folder.

The uninstaller will also not delete the registry entry which says that your app should start when you log in. If you want to keep your registry clean, you have to disable it in the settings app before uninstalling it.
{% endhint %}

### Using the Portable Version

If you don't want to install the app (or can't), you can use the portable version of the app. It's literally the same as the installable version; there are no differences. Again, go to the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases) and download *KeyboardSwitch-4.3.1-x64-win.zip* or *KeyboardSwitch-4.3.1-arm64-win.zip*. If you're not sure which one you should download, then it's most probably *x64*. Extract the archive to anywhere you want and start *KeyboardSwitchSettings.exe*. It will configure the app to run when you log in just like the installed version. The configuration for the portable version is also stored under your local app data folder.

## macOS

### Installing the App

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.pkg* file and run it to install the app. If your computer runs on an Apple CPU (e.g. M1), then you should get the *arm64* package. If your computer runs on an Intel CPU, then you should get the *x86\_64* package.

The installer will install multiple things:

* The Keyboard Switch Service app will be put into the */Library/Application Support* folder – you shouldn't run or interact with this app directly
* The Keyboard Switch Settings app will be put into the */Applications* folder
* The descriptor file for running the service app when you log in will be put into the */Library/LaunchAgents* folder

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

Immediately upon opening the app, a dialog window should appear which says that Keyboard Switch would like to control this computer using accessibility features. The app needs this to listen to the magic key combination while running in the background, and without these permissions it won't work. This dialog will appear only when you're installing the app for the first time. If you have installed it previously, then macOS will most probably remember that you gave the app appropriate permissions.

Click the *Open System Preferences* button on the dialog window. Enable the *Keyboard Switch* item. Close System Preferences and go back to the Keyboard Switch Settings app.

If the dialog window didn't appear for some reason, then press the *Start* button at the bottom of the window. The service app will start and immediately stop, because it doesn't have the accessibility permissions, and the dialog window will appear again.

You can configure the character mappings (you can read more about it in the next article) and other preferences. Start the app using the *Start* button. That's it! Now you're ready to use the Keyboard Switch service.

### Uninstalling the App

Many apps on macOS can be uninstalled just by deleting the app bundle from the */Applications* folder. This is not the case with Keyboard Switch. Multiple things should be done to remove it from the system. You shouldn't concern yourself with those things though – you should just run an uninstaller package, and it will remove Keyboard Switch.

As with the installer package, you can also get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download and run the *KeyboardSwitchUninstaller-4.3.1.pkg* file, and Keyboard Switch will be removed.

If you want to delete the app's configuration as well, then delete the *\[home]/Library/Application Support/Keyboard Switch* folder. You can also delete the app's log files by deleting the *\[home]/Library/Logs/Keyboard Switch* folder.

## Linux

### Installing the App

#### Prerequisites

There are several prerequisites for running the app on Linux:

* X11
* X Keyboard Extension (XKB) which is enabled by default.
* X Test Extension – used to simulate pressing keys like <kbd>Ctrl</kbd>+<kbd>C</kbd> and <kbd>Ctrl</kbd>+<kbd>V</kbd> for you.
* [xsel](https://github.com/kfish/xsel) (optional) – used to copy and paste text if the corresponding setting is enabled.
* Freedesktop conventions – used to make the service app start when you log in, and to make the settings app appear in the list of your installed apps (not required for the app itself though).

Keyboard Switch doesn't support Wayland (even with XWayland).

The most popular desktop systems (at least GNOME, KDE Plasma, Cinnamon, LXQt, and Xfce) all adhere to the Freedesktop protocols, so the last prerequisite is automatically available, unless you're running a very unusual setup.

Starting with version 4.2, Keyboard Switch uses native clipboard integration by default. This works well on newer desktop environments but doesn't work well on older versions. If you notice that Keyboard Switch doesn't work well on your system, then you can switch to using xsel instead. xsel must be installed manually though, and the service app must be restarted when this setting is changed.

[Click here](https://github.com/TolikPylypchuk/KeyboardSwitch/issues/105) to see the list of Linux distributions on which the app was tested.

{% hint style="warning" %}
If your desktop environment is GNOME, then you should restart it right after opening the settings app for the first time. If you're not sure which desktop environment you're using then it's most probably GNOME since it's the default one on Ubuntu, Debian, CentOS, Fedora and others (but not Linux Mint). Press <kbd>Alt</kbd>+<kbd>F2</kbd>, then type <kbd>r</kbd> and press <kbd>Enter</kbd>. This will restart GNOME.

This is not required though, but if you don't restart GNOME, then Keyboard Switch won't be able to switch your keyboard layout until you re-login or reboot your system.
{% endhint %}

#### Using a Deb Package

If you're running a Debian-based distribution (e.g., Ubuntu or Mint), then you can install Keyboard Switch using a deb package. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

The package takes care of the X Test extension, so you don't need to install it yourself.

After installation, the settings app will be available in the list of installed apps, and the service app will be configured to run at login.

Both the *amd64* and *arm64* versions are available.

#### Using an RPM Package

If you're running a RHEL-based distribution (e.g., Rocky Linux or Fedora), or SUSE, then you can install Keyboard Switch using an RPM package. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

The package takes care of the X Test extension, so you don't need to install it yourself.

{% hint style="info" %}
SUSE may complain that it cannot find libXtst when installing the app using the RPM package. This is because the package is targeted for RHEL and derivatives. You can ignore this warning and proceed with installation, but make sure that libXtst6 is installed before starting the app.
{% endhint %}

After installation, the settings app will be available in the list of installed apps, and the service app will be configured to run at login.

Both the *x86\_64* and *aarch64* versions are available.

#### Using a Tar Archive

Keyboard Switch is also available as a *tar.gz* file. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). You can then extract it to anywhere you like (e.g., into the */opt* directory). The deployed app includes two scripts – *install.sh* and *uninstall.sh*. *install.sh* adds the settings app to the list of installed apps. *uninstall.sh* deletes this configuration. These scripts will make changes only for the current user.

Both the *x64* and *arm64* versions are available.

The following scripts assume that the */opt* directory is writable. Substitute *x64* with *arm64* if needed.

Here are the steps required for installing the app on Debian, Ubuntu, Linux Mint, etc.:

```bash
sudo apt update
sudo apt install libxtst6  # Install the X Test Extension
tar -xzf keyboard-switch-4.3.1-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
```

Here are the steps required for installing the app on RHEL, Fedora, or Rocky Linux:

```bash
sudo dnf install epel-release  # Add the EPEL repository (not needed for Fedora)
sudo dnf install libXtst       # Install the X Test Extension
tar -xzf keyboard-switch-4.3.1-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
```

Here are the steps required for installing the app on SUSE (you may need to add the X11:XOrg repository to install libXtst6):

```bash
sudo zypper install libXtst6  # Install the X Test Extension
tar -xzf keyboard-switch-4.3.1-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
```

Here are the steps required for installing the app on Arch Linux:

```bash
sudo pacman -S libxtst  # Install the X Test Extension
tar -xzf keyboard-switch-4.3.1-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
```

### Uninstalling the App

For the deb and RPM packages, it's simple – just uninstall the package. For the *tar.gz* file, run the included *uninstall.sh* script, and delete the app's directory.

If you want to delete the app's configuration as well, then there are several ways to do that:

* For deb packages, you can run `apt remove` with the `--purge` option.
* For *tar.gz* files, you can run `uninstall.sh` with the `--purge` option.
* You can delete the *\~/.config/keyboard-switch* directory manually.

There is no way to delete the app configuration automatically for RPM packages.


# The Settings App

Keyboard Switch Settings is a simple app which controls the behavior of the Keyboard Switch service. You can find the app in the list of your installed apps (e.g. the Start menu on Windows). Here's how it looks:

<figure><picture><source srcset="/files/Z4l3QJojGsNjTYzDvomm" media="(prefers-color-scheme: dark)"><img src="https://308852972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fif8BSskr8Zuh4mGCGF1B%2Fuploads%2FOey2fbNLdJJkEKzMKDKq%2Fv4.3-screen-preferences.png?alt=media&amp;token=a270879e-e1f0-463a-8bdb-fafb5107a2c3" alt="The Keyboard Switch Settings app"></picture><figcaption><p>The Keyboard Switch Settings app</p></figcaption></figure>

The app is composed of four tabs:

* Character mappings: contains the settings which tell Keyboard Switch how to transform characters between layouts
* Preferences: contains other settings
* Sandbox: lets you play around with switching text
* About: contains info about the app

At the bottom there's a strip with the status of the Keyboard Switch service. If it's not running, you can press the *Start* button to start it manually (although usually you wouldn't do that because the service will start when you log in). If the service is running, you can stop it by pressing the *Stop* button. It won't actually kill it – it will send a *stop* command, and the service will do some clean-up and stop on its own. If it's taking a long time to stop, it may mean that something went wrong. In that case you can force it to stop by pressing the *Kill* button.

{% hint style="info" %}
If you change anything in the settings app, you can save it or cancel it. When you save it, the settings app sends a notification to the service app (if it's running) about changes in configuration, so you don't have to restart the service after saving.
{% endhint %}

The following articles describe each tab of the settings app in more detail.


# Preferences

The Preferences tab contains other settings which control the behavior of the Keyboard Switch service. Here's how it looks:

<figure><picture><source srcset="/files/Z4l3QJojGsNjTYzDvomm" media="(prefers-color-scheme: dark)"><img src="https://308852972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fif8BSskr8Zuh4mGCGF1B%2Fuploads%2FOey2fbNLdJJkEKzMKDKq%2Fv4.3-screen-preferences.png?alt=media&amp;token=a270879e-e1f0-463a-8bdb-fafb5107a2c3" alt="The preferences tab"></picture><figcaption><p>The preferences tab</p></figcaption></figure>

Following is the discussion on the many fields that are in this tab.

## Checkboxes

There are four checkboxes (five on Linux) at the top of the Preferences tab:

* Instant switching
* Switch layouts
* Start the service when you log in
* Show a message about uninstalled layouts
* Use xsel for clipboard integration (only on Linux)

The first checkbox controls whether the Keyboard Switch service should use instant switching or not. The default is yes. The service app needs to access the text to transform it, and for that it uses the clipboard. When instant switching is enabled, the service app will simulate pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> (or <kbd>Command</kbd>+<kbd>C</kbd> on macOS) to copy text into the clipboard. This is why you must first select the text before you let the service app switch it. After transforming the text, the service app will put it back into the clipboard and if the instant switching mode is enabled, it will simulate pressing <kbd>Ctrl</kbd>+<kbd>V</kbd> (or <kbd>Command</kbd>+<kbd>V</kbd> on macOS) to paste the new text instead of the selected text. If you disable this mode, you will have to manually copy the text before switching and then paste it afterwards. In addition, when this mode is enabled, the app will try to preserve the text that was in clipboard previously and restore it after switching (if the clipboard didn't contain text before switching, e.g., a file or a picture, it won't be restored).

The second checkbox controls whether the service app should switch the layout for you after transforming the text. The default is yes, and there's probably no reason to ever disable it. It just reduces the number of actions you have to do in order to get back on track with typing the text.

The third checkbox lets you control whether the service app will start when you log in. When you open the settings app for the first time, it configures the service app to run at startup automatically.

The fourth checkbox controls whether the settings app should show a warning about uninstalled layouts. If you install a new layout in the system, you should open the settings app and configure it in the Character Mappings tab. If you uninstall a layout, its configuration will still be saved in the app's settings, but it will essentially be redundant – the layout is not present in the system anymore and hence the service app won't need its configuration. When you uninstall a layout and open the settings app, it will show you a warning and a button to delete the unused configuration. If you want to ignore this warning for whatever reason, then uncheck this checkbox.

The fifth checkbox (which is only available on Linux) controls whether the clipboard integration is implemented directly through X11, or through xsel. Direct integration is the default, but may not work well on older desktop environments. If it doesn't, then xsel should be used instead. Unlike other options, changing this one requires restarting the service app. xsel must be installed manually for this option to work.

## Switch Settings

You can switch text just by pressing modifier keys. This is similar to switching keyboard layouts in Windows itself – the default key combination to switch layouts in Windows is <kbd>Alt</kbd>+<kbd>Shift</kbd>. You can control which key combination to press to switch text and how many times. The setting contains four fields:

* Modifier keys for switching forward
* Modifier keys for switching backward
* Press count
* Wait time (in milliseconds)

You can select <kbd>Ctrl</kbd>, <kbd>Alt</kbd>/<kbd>Option</kbd>, <kbd>Shift</kbd>*,* and <kbd>Win</kbd> (also known as <kbd>Super</kbd>, <kbd>Meta</kbd>, or <kbd>Command</kbd>), or their combination as modifier keys for switching. The default is <kbd>Ctrl</kbd>+<kbd>Shift</kbd> to switch forward, and <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> (<kbd>Ctrl</kbd>+<kbd>Option</kbd>+<kbd>Shift</kbd> on macOS) to switch backward.

You can also control how many times you should press those modifier keys to switch the text. The default is 2. Max value for this field is 10, but even that is way too much. Min value is 1, but be careful if you set it to 1, because then it would be easy to press it by accident.

Wait time controls how much time the service app waits before deciding that you're not intending on switching text. For example, let's say that the press count is 3, and wait time is 400 ms (which is the default value). You press the key combination. The app then waits for 400 ms to see whether you will press the key combination again. If you don't, then it realizes that you don't want to switch text. If you press the key combination again within this time, the app will then wait again for 400 ms. You then press the key combination for the third time, and the app realizes that you want to switch the text. The min value for this field is 100 ms (which usually makes the app give up waiting much too fast), and the max value for this field is 1000 ms (so, 1 full second, which is usually too slow). 400 ms is the sweet spot, but maybe it won't be for you. You should play around with this setting to figure out which value works best for you.

{% hint style="info" %}
Wait time is ignored if the press count is set to 1.
{% endhint %}

## Theme Settings

The way the settings app looks can be configured using the *App theme* and *Variant* dropdowns.

Three themes are supported:

* Fluent – this theme uses Fluent Design v2 and is the default one on Windows. The screenshots in these docs show the Fluent theme.
* macOS – this theme uses the default macOS look and feel and is the default one on macOS.
* Simple – this theme uses simple styles and is the default one on Linux.

Three variants are supported:

* Light
* Dark
* System – light or dark depending on system settings. This variant is the default one.


# Character Mappings

In order for the Keyboard Switch service to know how to map characters, ideally, you have to configure the character mappings yourself. The app reads the list of installed layouts in the system, so it knows which layouts you use and in what order. What it doesn't (and can't) know is the physical layout of your keyboard, so it doesn't know what happens if you press certain keys on your keyboard. Although it can auto-configure the mappings, and it will usually work well, there may be cases when it doesn't work well.

<figure><picture><source srcset="/files/JQ2PmzYjvIRuok3sOTWx" media="(prefers-color-scheme: dark)"><img src="https://308852972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fif8BSskr8Zuh4mGCGF1B%2Fuploads%2FCI05xpt9j8I9lWMfihHV%2Fv4.3-screen-char-mappings.png?alt=media&amp;token=1c91c543-7bd1-493c-b164-c55d92986928" alt="The character mappings tab"></picture><figcaption><p>The character mappings tab</p></figcaption></figure>

## Text vs Keyboard

This section explains *why* you need to configure character mappings for the app. If you're not interested, feel free to skip it.

Working with text and working with keyboard are two wildly different things. You, the user of a computer, usually work with a keyboard (or other input devices, but those don't matter here). This app however works with text (even though its name might suggest differently), and so text transformation during switching will most probably not be perfect.

Ideally you wouldn't have to configure the app at all – it would just know how to transform the text you mistyped into another layout. After all, the OS somehow knows which characters to produce when you press various keys! But going that way would be extremely difficult, if not impossible.

Firstly, pressing keys and entering characters are absolutely not the same thing. Many keys don't have corresponding characters at all, like <kbd>Ctrl</kbd> or <kbd>Page Up</kbd>. The same key press can produce different characters based on the state of other keys. For example, the <kbd>A</kbd> key usually produces **a**, but when <kbd>Shift</kbd> is down, the key produces **A**. And then there are dead keys – key combinations that produce one character by pressing two (or even three) keys. For example, in the US International layout, pressing <kbd>'</kbd> and then <kbd>A</kbd> will produce **á**.

Secondly, it's impossible to know which keys have been pressed just by looking at text. This is because the same character can be produced using different keys or key combinations (or it can be pasted, so the keyboard wouldn't be used at all).

So, in order to just know how to transform the text you've mistyped, the app would have to keep track of the keys you've pressed and then infer which of those pressed keys actually played a role in producing the mistyped text and then ask the OS which characters would be produced with the same key sequence. You can see how that's unreasonable. First of all, the app would have to track *all* the keys you press, and that would be quite sketchy. Would you trust an app which logs everything you type? I certainly wouldn't. And ethics aside, there still are technical issues. How many keys should the app track? What happens if the user pastes part of the text instead of typing it? Etc., etc.

And that's why the app uses a much simpler solution – it lets you, the user, figure out how the text should be transformed. The app can auto-configure the mappings using a simple method, but it's still up to you to check whether it's all correct.

## How Character Mappings Work

Here's how the tab looks if the configuration is empty:

<figure><picture><source srcset="/files/cIQc9s6kqo5offfdDeHz" media="(prefers-color-scheme: dark)"><img src="https://308852972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fif8BSskr8Zuh4mGCGF1B%2Fuploads%2Fh1g0FkDYmuFIFRIdgpoe%2Fv4.3-screen-char-mappings-empty.png?alt=media&amp;token=e95506e8-104e-4632-9fb3-e3ff7c5ad2c8" alt="The character mapping tab when the configuration is empty"></picture><figcaption><p>The character mappings tab when the configuration is empty</p></figcaption></figure>

You have to enter every character you can think of (which can be entered using your keyboard) into the text fields which correspond to layouts. For example, press the <kbd>Q</kbd> key, then press the <kbd>W</kbd> key, and so on. Then press <kbd>Shift</kbd>+<kbd>Q</kbd>, then <kbd>Shift</kbd>+<kbd>W</kbd> etc. to add uppercase letters.

You should press the keys *in the same order* for all layouts. Order matters here because the service will look at characters in same positions to determine how to transform the text. For example, let's say you have two layouts in your system: English (US) and Ukrainian (Enhanced). You put **q** as the first character in the text field for English, and **й** as the first character in the text field for Ukrainian (because that's the character you get when you press the <kbd>Q</kbd> key). Now the service will know that when it switches from English to Ukrainian, it should transform **q** to **й**. If the second characters are **w** and **ц** for English and Ukrainian respectively, then the service will transform **w** to **ц**.

If you don't want to map a certain character, you can put a space in its position in the other layout. The space character acts as a *don't map this character* command, though it should generally be avoided.

{% hint style="info" %}
This app is "Western-oriented". I developed it specifically to handle switching between Cyrillic and Latin scripts. I don't know how it will work (if at all) with Eastern languages/scripts.
{% endhint %}

## Auto-Configuration

Even though you have to do it only once, configuring character mappings is still cumbersome and error prone. That's why the app includes the auto-configuration feature. It's available only when all text fields are empty. The auto-configuration is quite simple (naïve even), and it shouldn't be 100% trusted, so you still have to check its output and fix mistakes or add other characters manually. But usually auto-configuration should be good enough.

Auto-configuration is available only when the character mapping configuration is completely empty.

{% hint style="info" %}
The character mappings are auto-configured automatically when the settings app is opened for the first time.
{% endhint %}

Here's how the tab looks after running auto-configuration:

<figure><picture><source srcset="/files/aS7C5BbJokSruW17hibm" media="(prefers-color-scheme: dark)"><img src="https://308852972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fif8BSskr8Zuh4mGCGF1B%2Fuploads%2FCnsnTOnKuCqJqXy6hpyK%2Fv4.3-screen-auto-configuration.png?alt=media&amp;token=b9db136e-ad42-4011-a1f3-8f1cf158e8cd" alt="The character mapping tab after auto-configuration"></picture><figcaption><p>The character mappings tab after auto-configuration</p></figcaption></figure>

### Windows and macOS

What auto-configuration does on Windows and macOS is basically ask the OS what would happen if certain keys were pressed using various layouts. There is no easy way to get the information about *all* keys on your keyboard, so it asks only about the most common ones. Here's the list of those keys for the US layout:

* All letter keys (<kbd>Q</kbd>, <kbd>W</kbd>, <kbd>E</kbd> etc.)
* Number keys
* Other common keys: <kbd>\[</kbd>, <kbd>]</kbd>, <kbd>;</kbd>, <kbd>'</kbd>, <kbd>,</kbd>, <kbd>.</kbd>, <kbd>/</kbd>, <kbd>\\</kbd>, <kbd>-</kbd>, <kbd>=</kbd>, and <kbd>\`</kbd>
* All those keys with the <kbd>Shift</kbd> key
* All those keys with the <kbd>AltGr</kbd>/<kbd>Option</kbd> key
* All those keys with the <kbd>Shift</kbd>+<kbd>AltGr</kbd>/<kbd>Option</kbd> keys

Not all of those key combinations actually produce characters for all layouts. So, after asking the OS about all of these keys, the app keeps only those character combinations which are defined for all layouts. For example, on Windows if you press <kbd>AltGr</kbd>+<kbd>U</kbd> in the Ukrainian layout, you will get **ґ**, but if you press those keys in the US layout, you won't get anything at all, so the app will just throw **ґ** out as it won't know how to map it to the US layout.

### Linux

Unlike Windows and macOS, there's actually a way to ask the OS (though X11) which characters are produced by all possible key presses. What the app will do is ask about characters produced by all key codes on all shift levels (there are 64 of them!). As with Windows, it will keep only those combinations which are defined for all layouts.

## Limitations

You can map every character only once per layout. Otherwise, it would be impossible to map characters deterministically.

Characters are always mapped one to one. You cannot map one character to several characters.

Dead keys are not supported.

The space character cannot be mapped to other characters. This is not really a limitation, because the space character is the same in every layout (at least that's the assumption).

The app doesn't play nicely with text if you switched the layout yourself in the middle of typing. If that's the case, the app will not switch it correctly, and you will have to fix some of it yourself.


# Other Tabs

Other tabs in the settings app include the Sandbox tab and the About tab.

## Sandbox

Sandbox is absurdly simple – it's just a text box. That's it! Here's how it looks:

<figure><picture><source srcset="/files/5td1JBwwJUYGGuDcDFG0" media="(prefers-color-scheme: dark)"><img src="https://308852972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fif8BSskr8Zuh4mGCGF1B%2Fuploads%2FLiDYZcyPvgFtrw5r2ZiE%2Fv4.3-screen-sandbox.png?alt=media&amp;token=0ed00369-cf42-48e1-a5be-075d87cf0ff7" alt="The sandbox tab"></picture><figcaption><p>The sandbox tab</p></figcaption></figure>

Sandbox lets you play around with switching text when you change the app's settings. It contains no logic whatsoever. It's literally just a text box.

## About

The About tab contains some general info about the app. Here's how it looks:

<figure><picture><source srcset="/files/iekvV5puyT0aKJqroD80" media="(prefers-color-scheme: dark)"><img src="https://308852972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fif8BSskr8Zuh4mGCGF1B%2Fuploads%2FQL1s6jQo5iXnlhnfqbpQ%2Fv4.3-screen-about.png?alt=media&amp;token=92819c2d-eac6-447f-97db-7d3a4c703047" alt="The about tab"></picture><figcaption><p>The about tab</p></figcaption></figure>

If you want more info, you can view the docs (these very pages).

You can also check whether updates for the app are available. If they are indeed available, then you can go to the releases page on GitHub to get them. The app doesn't support auto-updating, so you will have to install a newer version yourself. Remember that you should stop the service app before installing a newer version.

That's it for the settings app. If you want technical info about Keyboard Switch, you can check out the next articles.


# Command Line Interface

The Keyboard Switch service app has a CLI which you can use to control it. On Windows, it's not really convenient as GUI apps cannot output anything to the console, but it can be used as well.

The name of the executable is `KeyboardSwitch`. This article will assume it's installed on Linux in the `/opt/keyboard-switch` directory. On macOS, it's located in the `/Library/Application Support/Keyboard Switch.app/Contents/MacOS` directory.

## Commands

### Running the App

To start Keyboard Switch, simply run it in the terminal:

```
/opt/keyboard-switch/KeyboardSwitch &
```

The `&` makes the service app run in the background. On Windows, the `&` is not needed as GUI apps always run separately from the terminal.

Keyboard Switch is a single-instance app. If one instance is already running, and you start another one, it will immediately silently exit.

The app will exit immediately if it cannot find the settings file. This file is created when you run the settings app for the first time. This is done so that there's a lower chance that this app will run in an unconfigured state.

### Stopping the App

To stop Keyboard Switch, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --stop
```

If an instance of Keyboard Switch is running, this command will stop it. If no instance is running, it will do nothing.

### Reloading the Settings

To reload the settings of Keyboard Switch, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --reload-settings
```

If an instance of Keyboard Switch is running, this command will make it invalidate its current settings and reload them. If no instance is running, it will do nothing.

### Checking Whether the App Is Running

To check whether Keyboard Switch is running, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --check
```

If an instance of Keyboard Switch is running, this command will output `KeyboardSwitch is running`. Otherwise, it will output `KeyboardSwitch is not running`.

### Showing a Help Message

To show the help message, run either of the following:

```
/opt/keyboard-switch/KeyboardSwitch --help
/opt/keyboard-switch/KeyboardSwitch -?
```

### Command Formats

The aforementioned commands can be prefixed with `--`, `-`, or `/`. For example, to stop Keyboard Switch, you can specify `stop`, `-stop`, `--stop`, or `/stop`.

## Exit Codes

The following exit codes are available:

* `0` – The app has exited successfully.
* `1` – An unspecified error has occurred.
* `2` – The app cannot run, because its settings have an incompatible version. The app is backward-compatible with respect to settings versions – it will read the settings created by an older version and modify them to fit the current version. But it's not forward-compatible – version 4.3 will not work if the settings were created or updated by a newer version.
* `3` – `stop`, `reload-settings`, or `check` was specified as the command, but no instance of KeyboardSwitch is running.
* `4` – An invalid command was specified.
* `5` – The settings file was not found.
* `6` – The app doesn't have access to the accessibility API on macOS.


# Technical Stuff

Keyboard Switch is written using [C#](https://github.com/dotnet/csharplang) and [.NET 9](https://dotnet.microsoft.com/en-us/download/dotnet/8.0). Following is the list of technologies used in this app and some other technical aspects.

## UI

The Keyboard Switch Settings app is written using [Avalonia](https://avaloniaui.net), a cross-platform UI framework for .NET. I chose it because unlike other UI frameworks for .NET, it's cross-platform, and I had to do literally nothing for it to work on macOS and Linux as well. The styles are provided by [FluentAvalonia](https://github.com/amwx/FluentAvalonia), the [Devolutions macOS theme](https://github.com/Devolutions/avalonia-extensions), and Avalonia's simple theme.

Previous versions of the app used .NET Framework and WPF. Back then I didn't expect to have it working on different platforms.

Previous versions of the app also included a tray icon so you could see that the app is running. I removed it in version 3.0 as I don't see much value in keeping it and cluttering your tray.

## Core Logic

### Windows

The service app is just an app which runs in the background. I could have made it into a Windows service but decided against it when I read somewhere that Windows services cannot set up keyboard hooks. I didn't actually verify this info, so I'm not sure it's correct, but the background app approach works just fine, so it's likely to stay this way.

The service app calls various native functions from the Windows' *user32.dll*. It uses [Vanara](https://github.com/dahall/Vanara) to call them.

In the previous versions (up to 3.0) the service and the settings app were not separated. It was just an app running with a hidden window which showed up when you opened it. Having a hidden window always loaded is not that great of an idea, even though it used very little RAM.

### macOS

On macOS, the service app runs as a *launchd* service. *launchd* provides the ability to start at login. The settings app starts the service app through *launchd* as well.

macOS 10.15+ is required since it's the oldest version still supported by .NET.

The service app uses multiple native macOS frameworks:

* *CoreFoundation* – for low-level string, array, and pointer manipulation.
* *CarbonCore* (part of *CoreFoundation*) – for translating key codes with layout info into Unicode characters.
* *CoreGraphics* – for simulating keyboard events.
* *HIToolbox* – for working with keyboard layouts.
* *AppKit* – for working with the clipboard.

### Linux

At first, I decided to run the app as a *systemd* service, but it proved not to provide much value, so I've since reverted this decision.

The service app uses X11, especially the X Keyboard Extension, and the X Test Extension. Currently it doesn't work on Wayland, even through XWayland. It calls various native Xlib functions using P/Invoke directly.

The app interacts directly with X11 for clipboard integration – the code for this integration is based on code from Avalonia. It can also use [xsel](https://github.com/kfish/xsel) for clipboard integration instead.

If the Linux desktop environment is GNOME, then the app switches layouts a little differently than in other desktop environments. GNOME doesn't let apps switch layouts using X11 directly – it will immediately switch it back. Instead, the settings app adds a small GNOME Shell extension (which is simply called Switch Layout) and the app switches layouts through it. GNOME should be made aware of this extension after installation; hence you should restart it after starting the settings app. If you don't then the app will still work but won't be able to switch layouts until you log out or reboot.

### The Settings App

The core logic of the settings app is implemented using [ReactiveUI](https://www.reactiveui.net) as the MVVM framework. Also, [Splat](https://github.com/reactiveui/splat) is used for service location.

## App Structure

Keyboard Switch and Keyboard Switch Settings are published as self-contained single-file applications. The size difference between single-file applications and standard applications with shared libraries is negligible since single-file applications can be compressed.

On macOS, the two applications are located in separate directories – this is done because on macOS every application should be contained inside a bundle.

## The Global Keyboard Hook

The app uses [libuiohook](https://github.com/kwhat/libuiohook) to create a global keyboard hook. The library is cross-platform and supports almost all popular OSes and architectures. Since this library is native and it's non-trivial to build, I've developed a .NET wrapper for it, [SharpHook](https://github.com/TolikPylypchuk/SharpHook), so that I don't have to deal with a native library in this project.

Previously, the app used a Windows keyboard hook directly, but that doesn't work on other systems.

## Preferences

Preferences are stored in the user's local app data folder (under the *Keyboard Switch* directory) on Windows. I didn't put it into the normal app data folder because that one is shared if you use the same Windows account on multiple machines, and that kind of defeats the purpose of this app being configured for each machine individually.

On macOS, the settings are stored in the *\~/Library/Application Support/Keyboard Switch* directory.

On Linux, the settings are stored in the *\~/.config/keyboard-switch* directory.

This app stores settings as plain JSON files.

## Logging

This app uses a plain-text log file to log the stuff it’s doing and errors it encounters along the way. [Serilog](https://serilog.net) is used as the logging library.

On Windows and Linux, the log file is stored in the same folder as the preferences, and on macOS, it's stored in the *\~/Library/Logs/Keyboard Switch* directory. The log file is rolled over after reaching 10 MB.

If you really want to (and know how), you can change the logging configuration in the *appsettings.json* file. On Windows and Linux, this file is located in the same folder as the app itself. On macOS, this file is located in the bundle's resources folder, and you probably shouldn't change it as it may break the bundle's signature (though I'm not sure about that).

## Tests

There are very few tests and only for the core functionality. Honestly, I don't even know how to test the rest, because the rest of the app is essentially creating system-wide side effects, so don't think it's really testable. As for the settings app, well, I could test it, but that would take a lot of time, and the app is pretty simple, so I don't plan on doing it in the nearest future.

## Docs

The docs are built and hosted on [GitBook](https://www.gitbook.com).

Previously these articles were built using [Jekyll](https://jekyllrb.com) and hosted on [GitHub Pages](https://pages.github.com), and used the [Minimal Mistakes theme](https://mmistakes.github.io/minimal-mistakes).

## Installers

[WiX Toolset 6.0](https://www.firegiant.com/wixtoolset) is used to create the Windows installer. Previously, [WixSharp](https://github.com/oleg-shilo/wixsharp) was used, but the installer is really simple, so there is no need for it. Also, WixSharp requires .NET Framework, while WiX 4.0+ doesn't require it anymore.

The installer package for macOS is created using the default macOS tools.

The deb and RPM installers for Linux are also created using the default CLI tools.

## Building from Source

You can build Keyboard Switch from source if you like. All projects require .NET 8.

### The Projects

The app consists of 10 projects grouped into 3 folders:

* src:
  * *KeyboardSwitch*: The Keyboard Switch service itself
  * *KeyboardSwitch.Core*: Core functionality and interfaces for all projects
  * *KeyboardSwitch.Settings*: The Keyboard Switch Settings app
  * *KeyboardSwitch.Settings.Core*: The core logic of the settings app
  * *KeyboardSwitch.Windows*: The implementation of the core functionality for the Windows platform
  * *KeyboardSwitch.MacOS*: The implementation of the core functionality for the macOS platform
  * *KeyboardSwitch.Linux*: The implementation of the core functionality for the Linux platform
* test:
  * *KeyboardSwitch.Test*: The unit test project
* build:
  * *KeyboardSwitch.Build*: The NUKE project for building Keyboard Switch
  * *KeyboardSwitch.Windows.Installer*: The WiX installer project

### Building the App Itself

Keyboard Switch uses [NUKE](https://nuke.build) as its build system. It's not required to build Keyboard Switch, but it greatly simplifies creating the target artifacts. You should call the `./build.cmd` script from the root folder to run NUKE (the script is cross-platform).

The following targets are available (the default target is `Compile`):

* `Restore` – runs `dotnet restore` for all projects.
* `Clean` – runs `dotnet clean` for all projects.
* `Compile` – runs `dotnet build` for all projects.
* `Test` – runs `dotnet test` for the test project.
* `Publish` – runs `dotnet publish` for the *KeyboardSwitch* and *KeyboardSwitch.Settings* projects.
* `CreateZipArchive` – creates a *zip* archive which contains a portable distribution of Keyboard Switch.
* `CreateTarArchive` – creates a *tar.gz* archive which contains a portable distribution of Keyboard Switch.
* `CreateWindowsInstaller` – creates a Windows installer.
* `PrepareMacOSPackage` – prepares all files required for a macOS package.
* `CreateMacOSPackage` – creates a macOS package.
* `PrepareMacOSUninstallerPackage` – prepares all files required for a macOS uninstaller package.
* `CreateMacOSUninstallerPackage` – creates a macOS uninstaller package.
* `PrepareDebianPackage` – prepares all files required for a deb package.
* `CreateDebianPackage` – creates a deb package.
* `PrepareRpmPackage` – prepares all files required for an RPM package.
* `CreateRpmPackage` – creates an RPM package.

The Windows installer can be created on any OS. The macOS packages can only be created on macOS and require an Apple Developer account and certificates. The deb and RPM packages can only be created on Linux.

The following parameters are available:

* `Configuration` – `Debug` or `Release`. All targets except `Restore`, `Clean`, `Compile`, and `Test` require `Release` which is the default.
* `TargetOS` – `Windows`, `macOS`, or `Linux`. The currently running OS is the default. Windows installer requires `Windows`. macOS packages require `macOS`. Linux packages require `Linux`.
* `Platform` – `x64` or `arm64`. The currently running platform is the default.
* `PublishSingleFile` – `true` or `false`. All targets after `Publish` require `true`.
* `OutputFileSuffix` – the suffix to use on output files before the extension. For example, portable Windows distributions use the `win` suffix.

The following parameters are available for building macOS packages:

* `AppleId` – your Apple developer ID.
* `AppleTeamId` – your Apple team ID.
* `AppleApplicationCertificate` – the ID of your Apple application certificate.
* `AppleInstallerCertificate` – the ID of your Apple installer certificate.
* `NotaryToolKeychainProfile` – the Keychain profile to be used by `notarytool` when notarizing the package.

There are more parameters available for macOS, but they are only used when running in GitHub Actions. Certificates must be stored in Keychain for macOS packages to be built.

Here is the NUKE execution plan which shows the dependencies between targets:

<figure><img src="https://308852972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fif8BSskr8Zuh4mGCGF1B%2Fuploads%2Fr86MQCbsmwYahjIo1ybN%2Fv4.3-nuke-execution-plan.png?alt=media&amp;token=198083dd-a9cf-46fa-b675-018089803d98" alt="NUKE execution plan"><figcaption><p>NUKE execution plan</p></figcaption></figure>


# About

Keyboard Switch. Version 4.3.1. Created by [Tolik Pylypchuk](https://github.com/TolikPylypchuk).

## Acknowledgements

The UI for the settings app was created using [Avalonia](https://avaloniaui.net) with [ReactiveUI](https://www.reactiveui.net), [FluentAvalonia](https://github.com/amwx/FluentAvalonia), and the [Devolutions macOS theme](https://github.com/Devolutions/avalonia-extensions). The global keyboard hook is implemented using [libuiohook](https://github.com/kwhat/libuiohook). Windows installer created with [WiX Toolset](https://wixtoolset.org). Docs are built using [GitBook](https://www.gitbook.com). Icon made by [Smashicons](https://smashicons.com) from [www.flaticon.com](https://www.flaticon.com).

## Changelog

### [v4.3.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.3.1) (July 20, 2025)

* When Keyboard Switch is running on Windows, it doesn't cause some editors to insert random characters when <kbd>Alt</kbd>+<kbd>Arrow</kbd> keys are pressed anymore

### [v4.3.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.3.0) (June 30, 2025)

* The settings app now supports different themes for different OSes
* Dark mode is now available for the settings app
* The preferences tab is now the default tab in the settings app
* The application now works correctly when multiple users are logged in at the same time
* The application doesn't interfere with Alt codes on Windows anymore

### [v4.2.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.2.0) (August 14, 2024)

* Arm64 is now officially supported for Windows and Linux
* The converter has been removed
* A single modifier key can now be configured as the magic key for Keyboard Switch
* The app now integrates with the clipboard directly on Linux, without xsel, but this may not work well on older desktop environments, so integration through xsel is still possible
* The internal format of the settings was changed, so when updating to version 4.2 from older versions, the settings will be reverted to the defaults – you should reconfigure the app if you had custom configuration before
* Windows installer doesn't delete all users' configurations when uninstalling the app anymore
* Purging configuration is now available on Linux for deb packages and the *tar.gz* file
* The settings app now does auto-configuration by itself when being opened for the first time
* Switching layouts now works on GNOME 45+
* The application size and startup time has been reduced
* The application has been upgraded to .NET 8 and Avalonia 11
* WiX Toolset 5.0 is now used for the Windows installer, removing the need for .NET Framework
* NUKE is now used as the build tool

### [v4.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.1) (February 10, 2022)

* The app now works on macOS
* The app now supports Arm64 in addition to x64 (but the support is experimental for Windows and Linux)
* The app now switches layouts using native methods on Linux, hence layout settings are not needed anymore
* On Windows switching backward works correctly when there are more than two layouts
* The settings app will configure the service app to run at login when opened for the first time, instead of installers doing that – this means that the service app will be configured correctly for all users
* Windows Installer can delete all users' configurations when uninstalling the app

This is the first minor release which contains new features instead of just bug fixes, and it's a big one at that.

### [v4.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.0) (November 28, 2021)

* The app now works on Linux (via X11 only; Wayland is not supported)
* The legacy hot-key mode was removed – only the modifier keys mode is available
* The UI theme is overhauled
* The converter is hidden by default
* .NET 6 is used instead of .NET Core 3.1
* The app's performance was improved, though it's still not ideal

This is the first major version of the app which is not completely rewritten, though it was significantly changed. From now on, most changes (like macOS support) will come as minor versions, and version 4 will be the major version for the foreseeable future.

### [v3.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v3.0) (August 4, 2020)

* A completely rewritten app based on .NET Core and working as a truly UI-less app instead of an app with a hidden window
* The settings are now a separate app written with Avalonia instead of WPF
* Tray icon was removed
* Added the ability to switch between multiple layouts of the same language (e.g. QWERTY and Dvorak for English)
* Instant switching mode is not experimental anymore and enabled by default
* Added the ability to auto-configure character mappings
* Added checking for updates

### [v2.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v2.1) (April 1, 2018)

Minor bug fixes

### [v2.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v2.0) (January 13, 2018)

* Brand new installer for the app
* Instant switching mode
* Updated readme
* Updated configuration
* Minor UI updates
* Minor bug fixes

### [v1.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v1.1) (somewhere in 2015)

Minor bug fixes

### v1.0 (somewhere in 2015)

All the basic functionality:

* Switching text
* Starting at system startup
* Tray icon

## License

MIT License

Copyright (c) 2015 Anatoliy Pylypchuk

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


# Keyboard Switch

Welcome to the Keyboard Switch docs!

Keyboard Switch is an application which switches typed text as if it were typed with another keyboard layout.

If you ever write some text and then realize that you have written it using a wrong layout, you don't have to delete it and start over anymore. Just select the text, press a magic key combination, and that's it!

I hope this app will make your life at least 1% easier :)

## Quick Start

### Windows

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.msi* file and run it to install the app. If your computer runs on the x64 architecture, then you should get the *x64* installer. If your computer runs on the Arm architecture, then you should get the *arm64* installer. If you're not sure, then you most likely need the *x64* installer.

After installation, the Keyboard Switch Settings app will start. It may take some time as the app will do some initial setup. If it doesn't start for some reason, then find it in the list of your apps.

In the opened app, press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> twice instead.

### macOS

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.pkg* file and run it to install the app. If your computer runs on an Apple CPU (e.g. M1) then you should get the *arm64* package. If your computer runs on an Intel CPU then you should get the *x86\_64* package.

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

Immediately upon opening the app, a dialog window should appear which says that Keyboard Switch would like to control this computer using accessibility features. The app needs this to listen to the magic key combination while running in the background, and without these permissions it won't work.

Click the *Open System Preferences* button on the dialog window. Enable the *Keyboard Switch* item. Close System Preferences and go back to the Keyboard Switch Settings app.

In the settings app, press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Option</kbd>+<kbd>Shift</kbd> twice instead.

To uninstall Keyboard Switch you should run an uninstaller package. You can also get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

### Linux

The app is available as a deb package (for Debian-based distributions, such as Ubuntu, Mint etc.), an RPM package (for RHEL-based distributions, like Rocky Linux or Fedora, as well as SUSE), and a simple *tar.gz* file. You can get these files from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

{% hint style="info" %}
If you're using an RPM package, there are a couple things to note before installing the app (which you can find in the [installation](/4.2/usage-guides/installation#installing-the-app) article).
{% endhint %}

Bear in mind that Keyboard Switch only works on X11 – it won't work on Wayland (even with XWayland).

If you use the deb or RPM package, then simply install it either by double-clicking on it, or through the terminal. If you use the *tar.gz* file, then the set-up is not quite as quick, so you can read about it in the [installation page](/4.2/usage-guides/installation#installing-the-app).

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

{% hint style="warning" %}
If your desktop environment is GNOME, then you should restart it right after opening Keyboard Switch Settings. If you're not sure which desktop environment you're using then it's most probably GNOME since it's the default one on Ubuntu, Debian, Rocky, Fedora and others (but not Linux Mint). Press <kbd>Alt</kbd>+<kbd>F2</kbd>, then type <kbd>r</kbd> and press <kbd>Enter</kbd>. This will restart GNOME.
{% endhint %}

In the opened app, press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> twice instead.

## How the App Works

The app is composed of two parts: the Keyboard Switch service application and the Keyboard Switch Settings application. The service always runs in the background (and starts when you log into the system) and listens to key presses. When you press the magic key combination, it reacts by copying the selected text, transforming it, and pasting it for you. The settings app is used for configuring the service and for starting/stopping it manually.

Here are the basic steps you should take to switch the text:

* Type some text using an incorrect layout
* Realize your mistake
* Select the text (you can press <kbd>Ctrl</kbd>+`A` to select all text, or `Command`+<kbd>A</kbd> on macOS)
* Press the magic key combination (the default is pressing <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice)
* Profit

The app uses the list of your layouts in the same order as defined by the system. You can switch both forward and backward through this list. It will look at the current layout to determine how to switch text, so you shouldn't change the layout before switching. The app also automatically changes the layout, so you don't have to do it yourself.

The app uses the clipboard to get the text to transform and then puts the transformed text back into the clipboard. The app will try to preserve the text that was in the clipboard before switching and to restore it afterwards. It doesn't guarantee that the text will be restored though. Also, any non-text data (e.g., a file or a picture) will not be restored.

{% hint style="info" %}
**Note:** The app simulates pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> (or <kbd>Command</kbd>+<kbd>C</kbd> on macOS) to copy and <kbd>Ctrl</kbd>+<kbd>V</kbd> (or <kbd>Command</kbd>+<kbd>V</kbd> on macOS) to paste text. This is the default behavior for most applications. But if you are working in an app which behaves differently on those key presses (e.g., a terminal), this app will not be able to instantly switch text. You can disable this behavior and copy/paste the text manually.
{% endhint %}

## Supported Platforms

Keyboard Switch currently works on Windows 10/11 (version 1607 or later), macOS 10.15 or later, and Linux via X11. As for Linux, it needs several prerequisites to run (more on that on [the installation page](/4.2/usage-guides/installation#linux)).

The x64 and Arm64 architectures are both supported.


# Installation

## Windows

### Using a Windows Installer

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.msi* file and run it to install the app. If your computer runs on the x64 architecture, then you should get the *x64* installer. If your computer runs on the Arm architecture, then you should get the *arm64* installer. If you're not sure, then you most likely need the *x64* installer.

After installing the app, the installer will start the settings app. On the first start-up the settings app will configure the service to run when you log into the system.

When the settings app starts up you can configure the character mappings (you can read more about it in the next article) and other preferences. Start the app using the *Start* button at the bottom of the window. That's it! Now you're ready to use the Keyboard Switch service.

### Uninstalling the App

You can uninstall the app using Windows settings just like you would uninstall any other app.

{% hint style="warning" %}
The uninstaller will not delete the app's configuration. If you want to delete it, then go to your local app data folder, and delete the *KeyboardSwitch* folder.

The uninstaller will also not delete the registry entry which says that your app should start when you log in. If you want to keep your registry clean, you have to disable it in the settings app before uninstalling it.
{% endhint %}

### Using the Portable Version

If you don't want to install the app (or can't), you can use the portable version of the app. It's literally the same as the installable version; there are no differences. Again, go to the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases) and download *KeyboardSwitch-4.2.0-x64-win.zip* or *KeyboardSwitch-4.2.0-arm64-win.zip*. If you're not sure which one you should download, then it's most probably *x64*. Extract the archive to anywhere you want and start *KeyboardSwitchSettings.exe*. It will configure the app to run when you log in just like the installed version. The configuration for the portable version is also stored under your local app data folder.

## macOS

### Installing the App

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.pkg* file and run it to install the app. If your computer runs on an Apple CPU (e.g. M1), then you should get the *arm64* package. If your computer runs on an Intel CPU, then you should get the *x86\_64* package.

The installer will install multiple things:

* The Keyboard Switch Service app will be put into the */Library/Application Support* folder – you shouldn't run or interact with this app directly
* The Keyboard Switch Settings app will be put into the */Applications* folder
* The descriptor file for running the service app when you log in will be put into the */Library/LaunchAgents* folder

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

Immediately upon opening the app, a dialog window should appear which says that Keyboard Switch would like to control this computer using accessibility features. The app needs this to listen to the magic key combination while running in the background, and without these permissions it won't work. This dialog will appear only when you're installing the app for the first time. If you have installed it previously, then macOS will most probably remember that you gave the app appropriate permissions.

Click the *Open System Preferences* button on the dialog window. Enable the *Keyboard Switch* item. Close System Preferences and go back to the Keyboard Switch Settings app.

If the dialog window didn't appear for some reason, then press the *Start* button at the bottom of the window. The service app will start and immediately stop, because it doesn't have the accessibility permissions, and the dialog window will appear again.

You can configure the character mappings (you can read more about it in the next article) and other preferences. Start the app using the *Start* button. That's it! Now you're ready to use the Keyboard Switch service.

### Uninstalling the App

Many apps on macOS can be uninstalled just by deleting the app bundle from the */Applications* folder. This is not the case with Keyboard Switch. Multiple things should be done to remove it from the system. You shouldn't concern yourself with those things though – you should just run an uninstaller package, and it will remove Keyboard Switch.

As with the installer package, you can also get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download and run the *KeyboardSwitchUninstaller-4.2.0.pkg* file, and Keyboard Switch will be removed.

If you want to delete the app's configuration as well, then delete the *\[home]/Library/Application Support/Keyboard Switch* folder. You can also delete the app's log files by deleting the *\[home]/Library/Logs/Keyboard Switch* folder.

## Linux

### Installing the App

#### Prerequisites

There are several prerequisites for running the app on Linux:

* X11
* X Keyboard Extension (XKB) which is enabled by default
* X Test Extension – used to simulate pressing keys like <kbd>Ctrl</kbd>+<kbd>C</kbd> and <kbd>Ctrl</kbd>+<kbd>V</kbd> for you
* [xsel](https://github.com/kfish/xsel) (optional) – used to copy and paste text if the&#x20;
* Freedesktop conventions – used to make the service app start when you log in, and to make the settings app appear in the list of your installed apps (not required for the app itself though)

Keyboard Switch doesn't support Wayland (even with XWayland).

The most popular desktop systems (at least GNOME, KDE Plasma, Cinnamon, LXQt, and Xfce) all adhere to the Freedesktop protocols, so the last prerequisite is automatically available, unless you're running a very unusual setup.

Starting with version 4.2, Keyboard Switch uses native clipboard integration by default. This works well on newer desktop environments but doesn't work well on older versions. If you notice that Keyboard Switch doesn't work well on your system, then you can switch to using xsel instead. xsel must be installed manually though, and the service app must be restarted when this setting is changed.

[Click here](https://github.com/TolikPylypchuk/KeyboardSwitch/issues/94) to see the list of Linux distributions on which the app was tested.

{% hint style="warning" %}
If your desktop environment is GNOME, then you should restart it right after opening the settings app for the first time. If you're not sure which desktop environment you're using then it's most probably GNOME since it's the default one on Ubuntu, Debian, CentOS, Fedora and others (but not Linux Mint). Press <kbd>Alt</kbd>+<kbd>F2</kbd>, then type <kbd>r</kbd> and press <kbd>Enter</kbd>. This will restart GNOME.

This is not required though, but if you don't restart GNOME, then Keyboard Switch won't be able to switch your keyboard layout until you re-login or reboot your system.
{% endhint %}

#### Using a Deb Package

If you're running a Debian-based distribution (e.g., Ubuntu or Mint), then you can install Keyboard Switch using a deb package. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

The package takes care of the X Test extension, so you don't need to install it yourself.

After installation, the settings app will be available in the list of installed apps, and the service app will be configured to run at login.

Both the *amd64* and *arm64* versions are available.

#### Using an RPM Package

If you're running a RHEL-based distribution (e.g., Rocky Linux or Fedora), or SUSE, then you can install Keyboard Switch using an RPM package. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

The package takes care of the X Test extension, so you don't need to install it yourself.

{% hint style="info" %}
If you're using RHEL or Rocky Linux, then make sure that the EPEL repository is installed before installing Keyboard Switch. Otherwise, it won't be able to install xsel.
{% endhint %}

{% hint style="info" %}
SUSE may complain that it cannot find libXtst when installing the app using the RPM package. This is because the package is targeted for RHEL and derivatives. You can ignore this warning and proceed with installation, but make sure that libXtst6 is installed before starting the app.
{% endhint %}

After installation, the settings app will be available in the list of installed apps, and the service app will be configured to run at login.

Both the *x86\_64* and *aarch64* versions are available.

#### Using a Tar Archive

Keyboard Switch is also available as a *tar.gz* file. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). You can then extract it to anywhere you like (e.g., into the */opt* directory). The deployed app includes two scripts – *install.sh* and *uninstall.sh*. *install.sh* adds the settings app to the list of installed apps. *uninstall.sh* deletes this configuration. These scripts will make changes only for the current user.

Both the *x64* and *arm64* versions are available.

The following scripts assume that the */opt* directory is writable. Substitute *x64* with *arm64* if needed.

Here are the steps required for installing the app on Debian, Ubuntu, Linux Mint, etc.:

```
sudo apt update
sudo apt install libxtst6  # Install the X Test Extension
tar -xzf keyboard-switch-4.2.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
```

Here are the steps required for installing the app on RHEL, Fedora, or Rocky Linux:

```
sudo dnf install epel-release  # Add the EPEL repository (not needed for Fedora)
sudo dnf install libXtst       # Install the X Test Extension
tar -xzf keyboard-switch-4.2.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
```

Here are the steps required for installing the app on SUSE (you may need to add the X11:XOrg repository to install libXtst6):

```
sudo zypper install libXtst6  # Install the X Test Extension
tar -xzf keyboard-switch-4.2.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
```

Here are the steps required for installing the app on Arch Linux:

```
sudo pacman -S libxtst  # Install the X Test Extension
tar -xzf keyboard-switch-4.2.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
```

### Uninstalling the App

For the deb and RPM packages, it's simple – just uninstall the package. For the *tar.gz* file, run the included *uninstall.sh* script, and delete the app's directory.

If you want to delete the app's configuration as well, then there are several ways to do that:

* For deb packages, you can run `apt remove` with the `--purge` option.
* For *tar.gz* files, you can run `uninstall.sh` with the `--purge` option.
* You can delete the *\~/.config/keyboard-switch* directory manually.

There is no way to delete the app configuration automatically for RPM packages.


# The Settings App

Keyboard Switch Settings is a simple app which controls the behavior of the Keyboard Switch service. You can find the app in the list of your installed apps (e.g. the Start menu on Windows). Here's how it looks:

<figure><img src="https://1583900434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs0IRHdE3eReb4klBWH9K%2Fuploads%2F5O3V1oL7jlm7e5ucvtjz%2Fv4.2-screen-char-mappings.png?alt=media&amp;token=fa2f4103-dd0a-4404-88a4-01d5ee0afd5b" alt="The Keyboard Switch Settings app"><figcaption><p>The Keyboard Switch Settings app</p></figcaption></figure>

The app is composed of four tabs:

* Character mappings: contains the settings which tell Keyboard Switch how to transform characters between layouts
* Preferences: contains other settings
* Sandbox: lets you play around with switching text
* About: contains info about the app

At the bottom there's a strip with the status of the Keyboard Switch service. If it's not running, you can press the *Start* button to start it manually (although usually you wouldn't do that because the service will start when you log in). If the service is running, you can stop it by pressing the *Stop* button. It won't actually kill it – it will send a *stop* command, and the service will do some clean-up and stop on its own. If it's taking a long time to stop, it may mean that something went wrong. In that case you can force it to stop by pressing the *Kill* button.

{% hint style="info" %}
If you change anything in the settings app, you can save it or cancel it. When you save it, the settings app sends a notification to the service app (if it's running) about changes in configuration, so you don't have to restart the service after saving.
{% endhint %}

The following articles describe each tab of the settings app in more detail.


# Character Mappings

In order for the Keyboard Switch service to know how to map characters, ideally, you have to configure the character mappings yourself. The app reads the list of installed layouts in the system, so it knows which layouts you use and in what order. What it doesn't (and can't) know is the physical layout of your keyboard, so it doesn't know what happens if you press certain keys on your keyboard. Although it can auto-configure the mappings, and it will usually work well, there may be cases when it doesn't work well.

## Text vs Keyboard

This section explains *why* you need to configure character mappings for the app. If you're not interested, feel free to skip it.

Working with text and working with keyboard are two wildly different things. You, the user of a computer, usually work with a keyboard (or other input devices, but those don't matter here). This app however works with text (even though its name might suggest differently), and so text transformation during switching will most probably not be perfect.

Ideally you wouldn't have to configure the app at all – it would just know how to transform the text you mistyped into another layout. After all, the OS somehow knows which characters to produce when you press various keys! But going that way would be extremely difficult, if not impossible.

Firstly, pressing keys and entering characters are absolutely not the same thing. Many keys don't have corresponding characters at all, like <kbd>Ctrl</kbd> or <kbd>Page Up</kbd>. The same key press can produce different characters based on the state of other keys. For example, the <kbd>A</kbd> key usually produces **a**, but when <kbd>Shift</kbd> is down, the key produces **A**. And then there are dead keys – key combinations that produce one character by pressing two (or even three) keys. For example, in the US International layout, pressing <kbd>'</kbd> and then <kbd>A</kbd> will produce **á**.

Secondly, it's impossible to know which keys have been pressed just by looking at text. This is because the same character can be produced using different keys or key combinations (or it can be pasted, so the keyboard wouldn't be used at all).

So, in order to just know how to transform the text you've mistyped, the app would have to keep track of the keys you've pressed and then infer which of those pressed keys actually played a role in producing the mistyped text and then ask the OS which characters would be produced with the same key sequence. You can see how that's unreasonable. First of all, the app would have to track *all* the keys you press, and that would be quite sketchy. Would you trust an app which logs everything you type? I certainly wouldn't. And ethics aside, there still are technical issues. How many keys should the app track? What happens if the user pastes part of the text instead of typing it? Etc., etc.

And that's why the app uses a much simpler solution – it lets you, the user, figure out how the text should be transformed. The app can auto-configure the mappings using a simple method, but it's still up to you to check whether it's all correct.

## How Character Mappings Work

Here's how the tab looks if the configuration is empty:

<figure><img src="https://1583900434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs0IRHdE3eReb4klBWH9K%2Fuploads%2FprQGZmehizmY3P2QMbtl%2Fv4.2-screen-char-mappings-empty.png?alt=media&amp;token=015d19ae-e68d-4e9a-a2ac-41b633f82d2f" alt="The character mapping tab when the configuration is empty"><figcaption><p>The character mappings tab when the configuration is empty</p></figcaption></figure>

You have to enter every character you can think of (which can be entered using your keyboard) into the text fields which correspond to layouts. For example, press the <kbd>Q</kbd> key, then press the <kbd>W</kbd> key, and so on. Then press <kbd>Shift</kbd>+<kbd>Q</kbd>, then <kbd>Shift</kbd>+<kbd>W</kbd> etc. to add uppercase letters.

You should press the keys *in the same order* for all layouts. Order matters here because the service will look at characters in same positions to determine how to transform the text. For example, let's say you have two layouts in your system: English (US) and Ukrainian (Enhanced). You put **q** as the first character in the text field for English, and **й** as the first character in the text field for Ukrainian (because that's the character you get when you press the <kbd>Q</kbd> key). Now the service will know that when it switches from English to Ukrainian, it should transform **q** to **й**. If the second characters are **w** and **ц** for English and Ukrainian respectively, then the service will transform **w** to **ц**.

If you don't want to map a certain character, you can put a space in its position in the other layout. The space character acts as a *don't map this character* command, though it should generally be avoided.

{% hint style="info" %}
This app is "Western-oriented". I developed it specifically to handle switching between Cyrillic and Latin scripts. I don't know how it will work (if at all) with Eastern languages/scripts.
{% endhint %}

## Auto-Configuration

Even though you have to do it only once, configuring character mappings is still cumbersome and error prone. That's why the app includes the auto-configuration feature. It's available only when all text fields are empty. The auto-configuration is quite simple (naïve even), and it shouldn't be 100% trusted, so you still have to check its output and fix mistakes or add other characters manually. But usually auto-configuration should be good enough.

Auto-configuration is available only when the character mapping configuration is completely empty.

{% hint style="info" %}
The character mappings are auto-configured automatically when the settings app is opened for the first time.
{% endhint %}

Here's how the tab looks after running auto-configuration:

<figure><img src="https://1583900434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs0IRHdE3eReb4klBWH9K%2Fuploads%2FynrKLEjlJTCvEQYNnT3f%2Fv4.2-screen-auto-configuration.png?alt=media&amp;token=1ee368cb-60bf-426c-bb38-8c35f2f30a91" alt="The character mapping tab after auto-configuration"><figcaption><p>The character mappings tab after auto-configuration</p></figcaption></figure>

### Windows and macOS

What auto-configuration does on Windows and macOS is basically ask the OS what would happen if certain keys were pressed using various layouts. There is no easy way to get the information about *all* keys on your keyboard, so it asks only about the most common ones. Here's the list of those keys for the US layout:

* All letter keys (<kbd>Q</kbd>, <kbd>W</kbd>, <kbd>E</kbd> etc.)
* Number keys
* Other common keys: <kbd>\[</kbd>, <kbd>]</kbd>, <kbd>;</kbd>, <kbd>'</kbd>, <kbd>,</kbd>, <kbd>.</kbd>, <kbd>/</kbd>, <kbd>\\</kbd>, <kbd>-</kbd>, <kbd>=</kbd>, and <kbd>\`</kbd>
* All those keys with the <kbd>Shift</kbd> key
* All those keys with the <kbd>AltGr</kbd>/<kbd>Option</kbd> key
* All those keys with the <kbd>Shift</kbd>+<kbd>AltGr</kbd>/<kbd>Option</kbd> keys

Not all of those key combinations actually produce characters for all layouts. So, after asking the OS about all of these keys, the app keeps only those character combinations which are defined for all layouts. For example, on Windows if you press <kbd>AltGr</kbd>+<kbd>U</kbd> in the Ukrainian layout, you will get **ґ**, but if you press those keys in the US layout, you won't get anything at all, so the app will just throw **ґ** out as it won't know how to map it to the US layout.

### Linux

Unlike Windows and macOS, there's actually a way to ask the OS (though X11) which characters are produced by all possible key presses. What the app will do is ask about characters produced by all key codes on all shift levels (there are 64 of them!). As with Windows, it will keep only those combinations which are defined for all layouts.

## Limitations

You can map every character only once per layout. Otherwise, it would be impossible to map characters deterministically.

Characters are always mapped one to one. You cannot map one character to several characters.

Dead keys are not supported.

The space character cannot be mapped to other characters. This is not really a limitation, because the space character is the same in every layout (at least that's the assumption).

The app doesn't play nicely with text if you switched the layout yourself in the middle of typing. If that's the case, the app will not switch it correctly, and you will have to fix some of it yourself.


# Preferences

The Preferences tab contains other settings which control the behavior of the Keyboard Switch service. Here's how it looks:

<figure><img src="https://1583900434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs0IRHdE3eReb4klBWH9K%2Fuploads%2FARCNfVIkcnrgTulm4Buv%2Fv4.2-screen-preferences.png?alt=media&amp;token=a1a916be-498a-467a-9c50-af35824025ee" alt="The preferences tab"><figcaption><p>The preferences tab</p></figcaption></figure>

Following is the discussion on the many fields that are in this tab.

## Checkboxes

There are four checkboxes (five on Linux) at the top of the Preferences tab:

* Instant switching
* Switch layouts
* Start the service when you log in
* Show a message about uninstalled layouts
* Use xsel for clipboard integration (only on Linux)

The first checkbox controls whether the Keyboard Switch service should use instant switching or not. The default is yes. The service app needs to access the text to transform it, and for that it uses the clipboard. When instant switching is enabled, the service app will simulate pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> (or <kbd>Command</kbd>+<kbd>C</kbd> on macOS) to copy text into the clipboard. This is why you must first select the text before you let the service app switch it. After transforming the text, the service app will put it back into the clipboard and if the instant switching mode is enabled, it will simulate pressing <kbd>Ctrl</kbd>+<kbd>V</kbd> (or <kbd>Command</kbd>+<kbd>V</kbd> on macOS) to paste the new text instead of the selected text. If you disable this mode, you will have to manually copy the text before switching and then paste it afterwards. In addition, when this mode is enabled, the app will try to preserve the text that was in clipboard previously and restore it after switching (if the clipboard didn't contain text before switching, e.g., a file or a picture, it won't be restored).

The second checkbox controls whether the service app should switch the layout for you after transforming the text. The default is yes, and there's probably no reason to ever disable it. It just reduces the number of actions you have to do in order to get back on track with typing the text.

The third checkbox lets you control whether the service app will start when you log in. When you open the settings app for the first time, it configures the service app to run at startup automatically.

The fourth checkbox controls whether the settings app should show a warning about uninstalled layouts. If you install a new layout in the system, you should open the settings app and configure it in the Character Mappings tab. If you uninstall a layout, its configuration will still be saved in the app's settings, but it will essentially be redundant – the layout is not present in the system anymore and hence the service app won't need its configuration. When you uninstall a layout and open the settings app, it will show you a warning and a button to delete the unused configuration. If you want to ignore this warning for whatever reason, then uncheck this checkbox.

The fifth checkbox (which is only available on Linux) controls whether the clipboard integration is implemented directly through X11, or through xsel. Direct integration is the default, but may not work well on older desktop environments. If it doesn't, then xsel should be used instead. Unlike other options, changing this one requires restarting the service app. xsel must be installed manually for this option to work.

## Switch Settings

You can switch text just by pressing modifier keys. This is similar to switching keyboard layouts in Windows itself – the default key combination to switch layouts in Windows is <kbd>Alt</kbd>+<kbd>Shift</kbd>. You can control which key combination to press to switch text and how many times. The setting contains four fields:

* Modifier keys for switching forward
* Modifier keys for switching backward
* Press count
* Wait time (in milliseconds)

You can select <kbd>Ctrl</kbd>, <kbd>Alt</kbd>/<kbd>Option</kbd>, <kbd>Shift</kbd>*,* and <kbd>Win</kbd> (also known as <kbd>Super</kbd>, <kbd>Meta</kbd>, or <kbd>Command</kbd>), or their combination as modifier keys for switching. The default is <kbd>Ctrl</kbd>+<kbd>Shift</kbd> to switch forward, and <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> (<kbd>Ctrl</kbd>+<kbd>Option</kbd>+<kbd>Shift</kbd> on macOS) to switch backward.

You can also control how many times you should press those modifier keys to switch the text. The default is 2. Max value for this field is 10, but even that is way too much. Min value is 1, but be careful if you set it to 1, because then it would be easy to press it by accident.

Wait time controls how much time the service app waits before deciding that you're not intending on switching text. For example, let's say that the press count is 3, and wait time is 400 ms (which is the default value). You press the key combination. The app then waits for 400 ms to see whether you will press the key combination again. If you don't, then it realizes that you don't want to switch text. If you press the key combination again within this time, the app will then wait again for 400 ms. You then press the key combination for the third time, and the app realizes that you want to switch the text. The min value for this field is 100 ms (which usually makes the app give up waiting much too fast), and the max value for this field is 1000 ms (so, 1 full second, which is usually too slow). 400 ms is the sweet spot, but maybe it won't be for you. You should play around with this setting to figure out which value works best for you.

{% hint style="info" %}
Wait time is ignored if the press count is set to 1.
{% endhint %}


# Other Tabs

Other tabs in the settings app include the Sandbox tab and the About tab.

## Sandbox

Sandbox is absurdly simple – it's just a text box. That's it! Here's how it looks:

<figure><img src="https://1583900434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs0IRHdE3eReb4klBWH9K%2Fuploads%2F1rjPs30o5NjEFvsAWdNF%2Fv4.2-screen-sandbox.png?alt=media&amp;token=2f84d605-a699-479c-b992-9fb530a32a6a" alt="The sandbox tab"><figcaption><p>The sandbox tab</p></figcaption></figure>

Sandbox lets you play around with switching text when you change the app's settings. It contains no logic whatsoever. It's literally just a text box.

## About

The About tab contains some general info about the app. Here's how it looks:

<figure><img src="https://1583900434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs0IRHdE3eReb4klBWH9K%2Fuploads%2FRoU1PxZqbvwNWkuMjZcr%2Fv4.2-screen-about.png?alt=media&amp;token=83202c34-4630-48eb-82ca-a709657b08f0" alt="The about tab"><figcaption><p>The about tab</p></figcaption></figure>

If you want more info, you can view the docs (these very pages).

You can also check whether updates for the app are available. If they are indeed available, then you can go to the releases page on GitHub to get them. The app doesn't support auto-updating, so you will have to install a newer version yourself. Remember that you should stop the service app before installing a newer version.

That's it for the settings app. If you want technical info about Keyboard Switch, you can check out the next articles.


# Command Line Interface

The Keyboard Switch service app has a CLI which you can use to control it. On Windows, it's not really convenient as GUI apps cannot output anything to the console, but it can be used as well.

The name of the executable is `KeyboardSwitch`. This article will assume it's installed on Linux in the `/opt/keyboard-switch` directory. On macOS, it's located in the `/Library/Application Support/Keyboard Switch.app/Contents/MacOS` directory.

## Commands

### Running the App

To start Keyboard Switch, simply run it in the terminal:

```
/opt/keyboard-switch/KeyboardSwitch &
```

The `&` makes the service app run in the background. On Windows, the `&` is not needed as GUI apps always run separately from the terminal.

Keyboard Switch is a single-instance app. If one instance is already running, and you start another one, it will immediately silently exit.

The app will exit immediately if it cannot find the settings file. This file is created when you run the settings app for the first time. This is done so that there's a lower chance that this app will run in an unconfigured state.

### Stopping the App

To stop Keyboard Switch, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --stop
```

If an instance of Keyboard Switch is running, this command will stop it. If no instance is running, it will do nothing.

### Reloading the Settings

To reload the settings of Keyboard Switch, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --reload-settings
```

If an instance of Keyboard Switch is running, this command will make it invalidate its current settings and reload them. If no instance is running, it will do nothing.

### Checking Whether the App Is Running

To check whether Keyboard Switch is running, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --check
```

If an instance of Keyboard Switch is running, this command will output `KeyboardSwitch is running`. Otherwise, it will output `KeyboardSwitch is not running`.

### Showing a Help Message

To show the help message, run either of the following:

```
/opt/keyboard-switch/KeyboardSwitch --help
/opt/keyboard-switch/KeyboardSwitch -?
```

### Command Formats

The aforementioned commands can be prefixed with `--`, `-`, or `/`. For example, to stop Keyboard Switch, you can specify `stop`, `-stop`, `--stop`, or `/stop`.

## Exit Codes

The following exit codes are available:

* `0` – The app has exited successfully.
* `1` – An unspecified error has occurred.
* `2` – The app cannot run, because its settings have an incompatible version. The app is backward-compatible with respect to settings versions – it will read the settings created by an older version and modify them to fit the current version. But it's not forward-compatible – version 4.2 will not work if the settings were created or updated by a newer version.
* `3` – `stop`, `reload-settings`, or `check` was specified as the command, but no instance of KeyboardSwitch is running.
* `4` – An invalid command was specified.
* `5` – The settings file was not found.
* `6` – The app doesn't have access to the accessibility API on macOS.


# Technical Stuff

Keyboard Switch is written using [C#](https://github.com/dotnet/csharplang) and [.NET 8](https://dotnet.microsoft.com/en-us/download/dotnet/8.0). Following is the list of technologies used in this app and some other technical aspects.

## UI

The Keyboard Switch Settings app is written using [Avalonia](https://avaloniaui.net), a cross-platform UI framework for .NET. I chose it because unlike other UI frameworks for .NET, it's cross-platform, and I had to do literally nothing for it to work on macOS and Linux as well. The style is provided by [FluentAvalonia](https://github.com/amwx/FluentAvalonia).

Previous versions of the app used .NET Framework and WPF. Back then I didn't expect to have it working on different platforms.

Previous versions of the app also included a tray icon so you could see that the app is running. I removed it in version 3.0 as I don't see much value in keeping it and cluttering your tray.

## Core Logic

### Windows

The service app is just an app which runs in the background. I could have made it into a Windows service but decided against it when I read somewhere that Windows services cannot set up keyboard hooks. I didn't actually verify this info, so I'm not sure it's correct, but the background app approach works just fine, so it's likely to stay this way.

The service app calls various native functions from the Windows' *user32.dll*. It uses [Vanara](https://github.com/dahall/Vanara) to call them.

In the previous versions (up to 3.0) the service and the settings app were not separated. It was just an app running with a hidden window which showed up when you opened it. Having a hidden window always loaded is not that great of an idea, even though it used very little RAM.

### macOS

On macOS, the service app runs as a *launchd* service. *launchd* provides the ability to start at login. The settings app starts the service app through *launchd* as well.

macOS 10.15+ is required since it's the oldest version still supported by .NET.

The service app uses multiple native macOS frameworks:

* *CoreFoundation* – for low-level string, array, and pointer manipulation.
* *CarbonCore* (part of *CoreFoundation*) – for translating key codes with layout info into Unicode characters.
* *CoreGraphics* – for simulating keyboard events.
* *HIToolbox* – for working with keyboard layouts.
* *AppKit* – for working with the clipboard.

### Linux

At first, I decided to run the app as a *systemd* service, but it proved not to provide much value, so I've since reverted this decision.

The service app uses X11, especially the X Keyboard Extension, and the X Test Extension. Currently it doesn't work on Wayland, even through XWayland. It calls various native Xlib functions using P/Invoke directly.

The app interacts directly with X11 for clipboard integration – the code for this integration is based on code from Avalonia. It can also use [xsel](https://github.com/kfish/xsel) for clipboard integration instead.

If the Linux desktop environment is GNOME, then the app switches layouts a little differently than in other desktop environments. GNOME doesn't let apps switch layouts using X11 directly – it will immediately switch it back. Instead, the settings app adds a small GNOME Shell extension (which is simply called Switch Layout) and the app switches layouts through it. GNOME should be made aware of this extension after installation; hence you should restart it after starting the settings app. If you don't then the app will still work but won't be able to switch layouts until you log out or reboot.

### The Settings App

The core logic of the settings app is implemented using [ReactiveUI](https://www.reactiveui.net) as the MVVM framework. Also, [Splat](https://github.com/reactiveui/splat) is used for service location.

## App Structure

Keyboard Switch and Keyboard Switch Settings are published as self-contained single-file applications. The size difference between single-file applications and standard applications with shared libraries is negligible since single-file applications can be compressed.

On macOS, the two applications are located in separate directories – this is done because on macOS every application should be contained inside a bundle.

## The Global Keyboard Hook

The app uses [libuiohook](https://github.com/kwhat/libuiohook) to create a global keyboard hook. The library is cross-platform and supports almost all popular OSes and architectures. Since this library is native and it's non-trivial to build, I've developed a .NET wrapper for it, [SharpHook](https://github.com/TolikPylypchuk/SharpHook), so that I don't have to deal with a native library in this project.

Previously, the app used a Windows keyboard hook directly, but that doesn't work on other systems.

## Preferences

Preferences are stored in the user's local app data folder (under the *Keyboard Switch* directory) on Windows. I didn't put it into the normal app data folder because that one is shared if you use the same Windows account on multiple machines, and that kind of defeats the purpose of this app being configured for each machine individually.

On macOS, the settings are stored in the *\~/Library/Application Support/Keyboard Switch* directory.

On Linux, the settings are stored in the *\~/.config/keyboard-switch* directory.

This app stores settings as plain JSON files.

## Logging

This app uses a plain-text log file to log the stuff it’s doing and errors it encounters along the way. [Serilog](https://serilog.net) is used as the logging library.

On Windows and Linux, the log file is stored in the same folder as the preferences, and on macOS, it's stored in the *\~/Library/Logs/Keyboard Switch* directory. The log file is rolled over after reaching 10 MB.

If you really want to (and know how), you can change the logging configuration in the *appsettings.json* file. On Windows and Linux, this file is located in the same folder as the app itself. On macOS, this file is located in the bundle's resources folder, and you probably shouldn't change it as it may break the bundle's signature (though I'm not sure about that).

## Tests

There are very few tests and only for the core functionality. Honestly, I don't even know how to test the rest, because the rest of the app is essentially creating system-wide side effects, so don't think it's really testable. As for the settings app, well, I could test it, but that would take a lot of time, and the app is pretty simple, so I don't plan on doing it in the nearest future.

## Docs

The docs are built and hosted on [GitBook](https://www.gitbook.com).

Previously these articles were built using [Jekyll](https://jekyllrb.com) and hosted on [GitHub Pages](https://pages.github.com), and used the [Minimal Mistakes theme](https://mmistakes.github.io/minimal-mistakes).

## Installers

[WiX Toolset 5.0](https://www.firegiant.com/wixtoolset) is used to create the Windows installer. Previously, [WixSharp](https://github.com/oleg-shilo/wixsharp) was used, but the installer is really simple, so there is no need for it. Also, WixSharp requires .NET Framework, while WiX 4.0+ doesn't require it anymore.

The installer package for macOS is created using the default macOS tools.

The deb and RPM installers for Linux are also created using the default CLI tools.

## Building from Source

You can build Keyboard Switch from source if you like. All projects require .NET 8.

### The Projects

The app consists of 10 projects grouped into 3 folders:

* src:
  * *KeyboardSwitch*: The Keyboard Switch service itself
  * *KeyboardSwitch.Core*: Core functionality and interfaces for all projects
  * *KeyboardSwitch.Settings*: The Keyboard Switch Settings app
  * *KeyboardSwitch.Settings.Core*: The core logic of the settings app
  * *KeyboardSwitch.Windows*: The implementation of the core functionality for the Windows platform
  * *KeyboardSwitch.MacOS*: The implementation of the core functionality for the macOS platform
  * *KeyboardSwitch.Linux*: The implementation of the core functionality for the Linux platform
* test:
  * *KeyboardSwitch.Test*: The unit test project
* build:
  * *KeyboardSwitch.Build*: The NUKE project for building Keyboard Switch
  * *KeyboardSwitch.Windows.Installer*: The WiX installer project

### Building the App Itself

Keyboard Switch uses [NUKE](https://nuke.build) as its build system. It's not required to build Keyboard Switch, but it greatly simplifies creating the target artifacts. You should call the `./build.cmd` script from the root folder to run NUKE (the script is cross-platform).

The following targets are available (the default target is `Compile`):

* `Restore` – runs `dotnet restore` for all projects.
* `Clean` – runs `dotnet clean` for all projects.
* `Compile` – runs `dotnet build` for all projects.
* `Test` – runs `dotnet test` for the test project.
* `Publish` – runs `dotnet publish` for the *KeyboardSwitch* and *KeyboardSwitch.Settings* projects.
* `CreateZipArchive` – creates a *zip* archive which contains a portable distribution of Keyboard Switch.
* `CreateTarArchive` – creates a *tar.gz* archive which contains a portable distribution of Keyboard Switch.
* `CreateWindowsInstaller` – creates a Windows installer.
* `PrepareMacOSPackage` – prepares all files required for a macOS package.
* `CreateMacOSPackage` – creates a macOS package.
* `PrepareMacOSUninstallerPackage` – prepares all files required for a macOS uninstaller package.
* `CreateMacOSUninstallerPackage` – creates a macOS uninstaller package.
* `PrepareDebianPackage` – prepares all files required for a deb package.
* `CreateDebianPackage` – creates a deb package.
* `PrepareRpmPackage` – prepares all files required for an RPM package.
* `CreateRpmPackage` – creates an RPM package.

The Windows installer can be created on any OS. The macOS packages can only be created on macOS and require an Apple Developer account and certificates. The deb and RPM packages can only be created on Linux.

The following parameters are available:

* `Configuration` – `Debug` or `Release`. All targets except `Restore`, `Clean`, `Compile`, and `Test` require `Release` which is the default.
* `TargetOS` – `Windows`, `macOS`, or `Linux`. The currently running OS is the default. Windows installer requires `Windows`. macOS packages require `macOS`. Linux packages require `Linux`.
* `Platform` – `x64` or `arm64`. The currently running platform is the default.
* `PublishSingleFile` – `true` or `false`. All targets after `Publish` require `true`.
* `OutputFileSuffix` – the suffix to use on output files before the extension. For example, portable Windows distributions use the `win` suffix.

The following parameters are available for building macOS packages:

* `AppleId` – your Apple developer ID.
* `AppleTeamId` – your Apple team ID.
* `AppleApplicationCertificate` – the ID of your Apple application certificate.
* `AppleInstallerCertificate` – the ID of your Apple installer certificate.
* `NotaryToolKeychainProfile` – the Keychain profile to be used by `notarytool` when notarizing the package.

There are more parameters available for macOS, but they are only used when running in GitHub Actions. Certificates must be stored in Keychain for macOS packages to be built.

Here is the NUKE execution plan which shows the dependencies between targets:

<figure><img src="https://1583900434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs0IRHdE3eReb4klBWH9K%2Fuploads%2F1pNOOgPYsXFTY6PwVvYi%2Fv4.2-nuke-execution-plan.png?alt=media&amp;token=6a39c0cb-dada-44c9-9a84-bdad7965dd79" alt="NUKE execution plan"><figcaption><p>NUKE execution plan</p></figcaption></figure>


# About

Keyboard Switch. Version 4.2.0. Created by [Tolik Pylypchuk](https://github.com/TolikPylypchuk).

## Acknowledgements

The UI for the settings app was created using [Avalonia](https://avaloniaui.net) with [ReactiveUI](https://www.reactiveui.net) and [FluentAvalonia](https://github.com/amwx/FluentAvalonia). The global keyboard hook is implemented using [libuiohook](https://github.com/kwhat/libuiohook). Windows installer created with [WiX Toolset](https://wixtoolset.org). Docs are built using [GitBook](https://www.gitbook.com). Icon made by [Smashicons](https://smashicons.com) from [www.flaticon.com](https://www.flaticon.com).

## Changelog

### [v4.2.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.2.0) (14 August 2024)

* Arm64 is now officially supported for Windows and Linux
* The converter has been removed
* A single modifier key can now be configured as the magic key for Keyboard Switch
* The app now integrates with the clipboard directly on Linux, without xsel, but this may not work well on older desktop environments, so integration through xsel is still possible
* The internal format of the settings was changed, so when updating to version 4.2 from older versions, the settings will be reverted to the defaults – you should reconfigure the app if you had custom configuration before
* Windows installer doesn't delete all users' configurations when uninstalling the app anymore
* Purging configuration is now available on Linux for deb packages and the *tar.gz* file
* The settings app now does auto-configuration by itself when being opened for the first time
* Switching layouts now works on GNOME 45+
* The application size and startup time has been reduced
* The application has been upgraded to .NET 8 and Avalonia 11
* WiX Toolset 5.0 is now used for the Windows installer, removing the need for .NET Framework
* NUKE is now used as the build tool

### [v4.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.1) (10 February 2022)

* The app now works on macOS
* The app now supports Arm64 in addition to x64 (but the support is experimental for Windows and Linux)
* The app now switches layouts using native methods on Linux, hence layout settings are not needed anymore
* On Windows switching backward works correctly when there are more than two layouts
* The settings app will configure the service app to run at login when opened for the first time, instead of installers doing that – this means that the service app will be configured correctly for all users
* Windows Installer can delete all users' configurations when uninstalling the app

This is the first minor release which contains new features instead of just bug fixes, and it's a big one at that.

### [v4.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.0) (28 November 2021)

* The app now works on Linux (via X11 only; Wayland is not supported)
* The legacy hot-key mode was removed – only the modifier keys mode is available
* The UI theme is overhauled
* The converter is hidden by default
* .NET 6 is used instead of .NET Core 3.1
* The app's performance was improved, though it's still not ideal

This is the first major version of the app which is not completely rewritten, though it was significantly changed. From now on, most changes (like macOS support) will come as minor versions, and version 4 will be the major version for the foreseeable future.

### [v3.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v3.0) (4 August 2020)

* A completely rewritten app based on .NET Core and working as a truly UI-less app instead of an app with a hidden window
* The settings are now a separate app written with Avalonia instead of WPF
* Tray icon was removed
* Added the ability to switch between multiple layouts of the same language (e.g. QWERTY and Dvorak for English)
* Instant switching mode is not experimental anymore and enabled by default
* Added the ability to auto-configure character mappings
* Added checking for updates

### [v2.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v2.1) (1 April 2018)

Minor bug fixes

### [v2.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v2.0) (13 January 2018)

* Brand new installer for the app
* Instant switching mode
* Updated readme
* Updated configuration
* Minor UI updates
* Minor bug fixes

### [v1.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v1.1) (somewhere in 2015)

Minor bug fixes

### v1.0 (somewhere in 2015)

All the basic functionality:

* Switching text
* Starting at system startup
* Tray icon

## License

MIT License

Copyright (c) 2015 Anatoliy Pylypchuk

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


# Keyboard Switch

Welcome to the Keyboard Switch docs!

Keyboard Switch is an application which switches typed text as if it were typed with another keyboard layout.

If you ever write some text and then realize that you have written it using a wrong layout, you don't have to delete it and start over anymore. Just select the text, press a magic key combination, and that's it!

I hope this app will make your life at least 1% easier :)

{% hint style="info" %}
If you're using version 4.1, then you should upgrade to version 4.3 since it contains numerous improvements.
{% endhint %}

## Quick Start

### Windows

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.msi* file and run it to install the app.

After installation, the Keyboard Switch Settings app will start. It may take some time as the app will do some initial setup. If it doesn't start for some reason, then find it in the list of your apps.

In the opened app, press the *Auto-configure* button.

Press *Save*.

Press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text, and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> twice instead.

### macOS

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.pkg* file and run it to install the app. If your computer runs on an Intel CPU, then you should get the *x86\_64* package. If your computer runs on an Apple CPU (e.g. M1), then you should get the *arm64* package.

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

Immediately upon opening the app, a dialog window should appear which says that Keyboard Switch would like to control this computer using accessibility features. The app needs this to listen to the magic key combination while running in the background and without these permissions it won't work.

Click the *Open System Preferences* button on the dialog window. Enable the *Keyboard Switch* item. Close System Preferences and go back to the Keyboard Switch Settings app.

In the settings app, press the *Auto-configure* button.

Press *Save*.

Press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Option</kbd>+<kbd>Shift</kbd> twice instead.

To uninstall Keyboard Switch, you should run an uninstaller package. You can also get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

### Linux

The app is available as a deb package (for Debian-based distributions, such as Ubuntu, Mint etc.), an RPM package (for RHEL-based distributions, like CentOS or Fedora, as well as SUSE), and a simple *tar.gz* file. You can get these files from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

{% hint style="info" %}
If you're using an RPM package, there are a couple things to note before installing the app (which you can find in the [installation](/4.1/usage-guides/installation#installing-the-app) article).
{% endhint %}

Bear in mind that KeyboardSwitch only works on X11 – it won't work on Wayland (even with XWayland).

If you use the deb or RPM package, then simply install it either by double-clicking on it, or through the terminal. If you use the *tar.gz* file, then the set-up is not quite as quick, so you can read about it in the [installation page](/4.1/usage-guides/installation#installing-the-app).

{% hint style="warning" %}
If your desktop environment is GNOME then you should restart it right after installation. If you're not sure which desktop environment you're using then it's most probably GNOME since it's the default one on Ubuntu, Debian, CentOS, Fedora and others (but not Linux Mint). Press <kbd>Alt</kbd>+<kbd>F2</kbd>, then type <kbd>r</kbd> and press <kbd>Enter</kbd>. This will restart GNOME.
{% endhint %}

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

In the opened app, press the *Auto-configure* button.

Press *Save*.

Press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> twice instead.

## How the App Works

The app is composed of two parts: the Keyboard Switch service and the Keyboard Switch Settings app. The service always runs in the background (and starts when you log into the system) and listens to key presses. When you press the magic key combination, it reacts by copying the selected text, transforming it, and pasting it for you. The settings app is used for configuring the service and for starting/stopping it manually.

Here are the basic steps you should take to switch the text:

* Type some text using an incorrect layout
* Realize your mistake
* Select the text (you can press <kbd>Ctrl</kbd>+<kbd>A</kbd> to select all text, or <kbd>Command</kbd>+<kbd>A</kbd> on macOS)
* Press the magic key combination (the default is pressing <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice)
* Profit

The app uses the list of your layouts in the same order as defined by the system. You can switch both forward and backward through this list. It will look at the current layout to determine how to switch text, so you shouldn't change the layout before switching. The app also automatically changes the layout, so you don't have to do it yourself.

The app uses the clipboard to get the text to transform and then puts the transformed text back into the clipboard. The app will try to preserve the text that was in the clipboard before switching and to restore it afterwards. It doesn't guarantee that the text will be restored though. Also, any non-text data (e.g., a file or a picture) will not be restored.

{% hint style="info" %}
The app simulates pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> (or <kbd>Command</kbd>+<kbd>C</kbd> on macOS) to copy and <kbd>Ctrl</kbd>+`V` (or <kbd>Command</kbd>+<kbd>V</kbd> on macOS) to paste text. This is the default behavior for most applications. But if you are working in an app which behaves differently on those key presses (e.g., a terminal), this app will not be able to instantly switch text. You can disable this behavior and copy/paste the text manually.
{% endhint %}

## Supported Platforms

Keyboard Switch currently works on Windows 10/11, macOS 10.11+, and Linux via X11. It can probably work on older versions of Windows as well, but I'm not going to support them. As for Linux, it needs several prerequisites to run (more on that on [the installation page](/4.1/usage-guides/installation#linux)).

The x64 and Arm64 architectures are both supported, but for Windows and Linux the latter is experimental. Arm64 is fully supported starting from version 4.2.


# Installation

## Windows

### Using a Windows Installer

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.msi* file and run it to install the app.

After installing the app, the installer will run the settings app. Currently it's not really optimized, so the startup time is not perfect; it can take a couple seconds for the app to get started. On the first start-up the settings app will configure the service to run when you log into the system.

When the settings app starts up you should configure the character mappings (you can read more about it in the next article). After you have configured the character mappings and possibly some other preferences, start the app using the *Start* button at the bottom of the window. That's it! Now you're ready to use the Keyboard Switch service.

Current only the x64 version can be installed with an installer. If you want the Arm64 version, then you should use a portable version or [build the installer yourself](/4.1/other/technical#building-the-windows-installer).

### Uninstalling the App

You can uninstall the app using the Settings app just like you would uninstall any other app.

{% hint style="warning" %}
The installer will not delete the registry entry which says that your app should start when you log in. If you want to keep your registry clean, you have to disable it in the settings app before uninstalling it.
{% endhint %}

Upon uninstallation the installer will ask whether you want to delete the app's configuration as well. If you choose not to delete the configuration, you can delete it later manually at any other time. It's stored under the user's local app data folder.

### Using the Portable Version

If you don't want to install the app (or can't), you can use the portable version of the app. It's literally the same as the installable version; there are no differences. Again, go to the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases) and download *KeyboardSwitch-4.1-x64-win.zip* or *KeyboardSwitch-4.1-arm64-win.zip*. If you're not sure which one you should download, then it's most probably x64. Extract the archive to anywhere you want and start *KeyboardSwitchSettings.exe*. It will configure the app to run when you log in just like the installed version. The configuration for the portable version is also stored under the user's local app data folder.

## macOS

### Installing the App

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.pkg* file and run it to install the app. If your computer runs on an Intel CPU, then you should get the *x86\_64* package. If your computer runs on an Apple CPU (e.g. M1), then you should get the *arm64* package.

The installer will install multiple things:

* The Keyboard Switch Service app will be put into the */opt* folder – you shouldn't run or interact with this app directly
* The Keyboard Switch Settings app will be put into the */Applications* folder
* The descriptor file for running the service app when you log in will be put into the */Library/LaunchAgents* folder

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

Immediately upon opening the app, a dialog window should appear which says that Keyboard Switch would like to control this computer using accessibility features. The app needs this to listen to the magic key combination while running in the background, and without these permissions it won't work. This dialog will appear only when you're installing the app for the first time. If you have installed it previously, then macOS will most probably remember that you gave the app appropriate permissions.

Click the *Open System Preferences* button on the dialog window. Enable the *Keyboard Switch* item. Close System Preferences and go back to the Keyboard Switch Settings app.

If the dialog window didn't appear for some reason, then press the *Start* button at the bottom of the window. The service app will start and immediately stop, because it doesn't have the accessibility permissions, and the dialog window will appear again.

You should configure the character mappings (you can read more about it in the next article). After you have configured the character mappings and possibly some other preferences, start the app using the *Start* button. That's it! Now you're ready to use the Keyboard Switch service.

### Uninstalling the App

Many apps on macOS can be uninstalled just by deleting the app bundle from the */Applications* folder. This is not the case with Keyboard Switch. Multiple things should be done to remove it from the system. You shouldn't concern yourself with those things though – you should just run an uninstaller package, and it will remove Keyboard Switch.

As with the installer package, you can also get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download and run the *KeyboardSwitchUninstaller-4.1.pkg* file, and Keyboard Switch will be removed.

If you want to delete the app's configuration as well, then delete the hidden *.keyboard-switch* folder in your home folder.

## Linux

### Installing the App

#### Prerequisites

There are several prerequisites for running the app on Linux:

* X11
* X Keyboard Extension (XKB) which is enabled by default
* X Test Extension – used to simulate pressing keys like <kbd>Ctrl</kbd>+<kbd>C</kbd> and <kbd>Ctrl</kbd>+<kbd>V</kbd> for you
* [xsel](https://github.com/kfish/xsel) – used to copy and paste text
* Bash – used to call xsel, but you don't need to have it as your default shell
* Freedesktop conventions – used to make the service app start when you log in, and to make the settings app appear in the list of your installed apps (not required for the app itself though)

Keyboard Switch doesn't support Wayland (even with XWayland).

The most popular desktop systems (at least GNOME, KDE Plasma, Cinnamon, and LXQt) all adhere to the Freedesktop protocols, so the last prerequisite is automatically available, unless you're running a very unusual setup.

[Click here](https://github.com/TolikPylypchuk/KeyboardSwitch/issues/76) to see the list of Linux distributions on which the app was tested.

{% hint style="warning" %}
If your desktop environment is GNOME, then you should restart it right after installation. If you're not sure which desktop environment you're using then it's most probably GNOME since it's the default one on Ubuntu, Debian, CentOS, Fedora and others (but not Linux Mint). Press <kbd>Alt</kbd>+<kbd>F2</kbd>, then type <kbd>r</kbd> and press <kbd>Enter</kbd>. This will restart GNOME.
{% endhint %}

#### Using a Deb Package

If you're running a Debian-based distribution (e.g., Ubuntu or Mint), then you can install Keyboard Switch using a deb package. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

The package takes care of xsel and the X Test extension, so you don't need to install them yourself.

After installation, the settings app will be available in the list of installed apps, and the service app will be configured to run at login.

Both the *amd64* and *arm64* versions are available, but the latter is experimental.

#### Using an RPM Package

If you're running a RHEL-based distribution (e.g., CentOS or Fedora), or SUSE, then you can install Keyboard Switch using an RPM package. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

The package takes care of xsel and the X Test extension, so you don't need to install them yourself.

{% hint style="info" %}
If you're using RHEL, CentOS, or Rocky Linux, then make sure that the EPEL repository is installed before installing Keyboard Switch. Otherwise, it won't be able to install xsel.
{% endhint %}

{% hint style="info" %}
SUSE may complain that it cannot find libXtst when installing the app using the RPM package. This is because the package is targeted for RHEL and derivatives. You can ignore this warning and proceed with installation, but make sure that libXtst6 is installed before starting the app.
{% endhint %}

After installation, the settings app will be available in the list of installed apps, and the service app will be configured to run at login.

Both the *x86\_64* and *aarch64* versions are available, but the latter is experimental.

#### Using a Tar Archive

Keyboard Switch is also available as a *tar.gz* fie. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). You can then extract it to anywhere you like (e.g., into the */opt* directory). The deployed app includes two scripts – *install.sh* and *uninstall.sh*. *install.sh* adds the settings app to the list of installed apps. *uninstall.sh* deletes this configuration.

Both the *x64* and *arm64* versions are available, but the latter is experimental.

The following scripts assume that the */opt* directory is writable.

Here are the steps required for installing the app on Debian, Ubuntu, Linux Mint, etc.:

```
sudo apt update
sudo apt install xsel libxtst6  # Install xsel and the X Test Extension
tar -xzf keyboard-switch-4.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
```

Here are the steps required for installing the app on RHEL, CentOS, Fedora, or Rocky Linux (use `yum` instead of `dnf` on older systems):

```
sudo dnf install epel-release  # Add the EPEL repository (not needed for Fedora)
sudo dnf install xsel          # Install xsel
sudo dnf install libXtst       # Install the X Test Extension
tar -xzf keyboard-switch-4.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
```

Here are the steps required for installing the app on SUSE (you may need to add the X11:XOrg repository to install libXtst6):

```
sudo zypper install xsel      # Install xsel
sudo zypper install libXtst6  # Install the X Test Extension
tar -xzf keyboard-switch-4.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
```

Here are the steps required for installing the app on Arch Linux:

```
sudo pacman -S xsel     # Install xsel
sudo pacman -S libxtst  # Install the X Test Extension
tar -xzf keyboard-switch-4.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
./install.sh
```

### Uninstalling the App

For the deb and RPM packages, it's simple – just uninstall the package. For the *tar.gz* file, run the included *uninstall.sh* script, and delete the app's directory. If you want to delete the app's configuration as well, then delete the *\~/.keyboard-switch* directory.


# The Settings App

Keyboard Switch Settings is a simple app which controls the behavior of the Keyboard Switch service. You can find the app in the list of your installed apps (e.g. the Start menu on Windows). Here's how it looks:

![](https://3979224463-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fx2tIzR5h95gzWny0Rez6%2Fuploads%2FyqaPzmhd5BmUPQLb2NEb%2Fv4.1-screen-char-mappings.png?alt=media\&token=15d2f8a4-96f0-480d-9a25-640055562976)

The app is composed of six tabs:

* Character mappings: contains the settings which tell Keyboard Switch how to transform characters between layouts
* Preferences: contains other settings
* Converter: lets you manually convert text between arbitrary custom layouts (hidden by default)
* Converter settings: contains the list of custom layouts for the converter (hidden by default)
* Sandbox: lets you play around with switching the text
* About: contains info about the app

At the bottom there's a strip with the status of the Keyboard Switch service. If it's not running, you can press the *Start* button to start it manually (although usually you wouldn't do that because the service will start when you log in). If the service is running, you can stop it by pressing the *Stop* button. It won't actually kill it – it will send a *stop* command, and the service will do some clean-up and stop on its own. If it's taking a long time to stop, it may mean that something went wrong. In that case you can force it to stop by pressing the *Kill* button.

{% hint style="info" %}
If you change anything in the settings app, you can save it or cancel it. When you save it, the settings app sends a notification to the service app (if it's running) about changes in configuration, so you don't have to restart the service after saving.
{% endhint %}

The following articles describe each tab of the settings app in more detail.


# Character Mappings

In order for the Keyboard Switch service to know how to map characters, you have to configure the character mappings yourself. The app reads the list of installed layouts in the system, so it knows which layouts you use and in what order. What it doesn't (and can't) know is the physical layout of your keyboard, so it doesn't know what happens if you press certain keys on your keyboard.

## Text vs Keyboard

This section explains *why* you need to configure character mappings for the app. If you're not interested, feel free to skip it.

Working with text and working with keyboard are two wildly different things. You, the user of a computer, usually work with a keyboard (or other input devices, but those don't matter here). This app however works with text (even though its name might suggest differently), and so text transformation during switching will most probably not be perfect.

Ideally you wouldn't have to configure the app at all – it would just know how to transform the text you mistyped into another layout. After all, the OS somehow knows which characters to produce when you press various keys! But going that way would be extremely difficult, if not impossible.

Firstly, pressing keys and entering characters are absolutely not the same thing. Many keys don't have corresponding characters at all, like <kbd>Ctrl</kbd> or <kbd>Page Up</kbd>. The same key press can produce different characters based on the state of other keys. For example, the <kbd>A</kbd> key usually produces **a**, but when <kbd>Shift</kbd> is down, the key produces **A**. And then there are dead keys – key combinations that produce one character by pressing two (or even three) keys. For example, in the US International layout, pressing <kbd>'</kbd> and then <kbd>A</kbd> will produce **á**.

Secondly, it's impossible to know which keys have been pressed just by looking at text. This is because the same character can be produced using different keys or key combinations (or it can be pasted, so the keyboard wouldn't be used at all).

So, in order to just know how to transform the text you've mistyped, the app would have to keep track of the keys you've pressed and then infer which of those pressed keys actually played a role in producing the mistyped text and then ask the OS which characters would be produced with the same key sequence. You can see how that's unreasonable. First of all, the app would have to track *all* the keys you press, and that would be quite sketchy. Would you trust an app which logs everything you type? I certainly wouldn't. And ethics aside, there still are technical issues. How many keys should the app track? What happens if the user pastes part of the text instead of typing it? Etc., etc.

And that's why the app uses a much simpler solution – it lets you, the user, figure out how the text should be transformed. The app can auto-configure the mappings using a simple method, but it's still up to you to check whether it's all correct.

## How Character Mappings Work

Here's how the tab looks when the app is opened for the first time:

![The character mappings tab when the configuration is empty](https://3979224463-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fx2tIzR5h95gzWny0Rez6%2Fuploads%2FOoTqd2v59hmH3gfi0Y66%2Fv4.1-screen-char-mappings-empty.png?alt=media\&token=ae0ac305-aeb5-44df-bbc9-d6ffddb1a114)

You have to enter every character you can think of (which can be entered using your keyboard) into the text fields which correspond to layouts. For example, press the <kbd>Q</kbd> key, then press the <kbd>W</kbd> key, and so on. Then press <kbd>Shift</kbd>+<kbd>Q</kbd>, then <kbd>Shift</kbd>+<kbd>W</kbd> etc. to add uppercase letters.

You should press the keys *in the same order* for all layouts. Order matters here because the service will look at characters in same positions to determine how to transform the text. For example, let's say you have two layouts in your system: English (US) and Ukrainian (Enhanced). You put **q** as the first character in the text field for English, and **й** as the first character in the text field for Ukrainian (because that's the character you get when you press the <kbd>Q</kbd> key). Now the service will know that when it switches from English to Ukrainian, it should transform **q** to **й**. If the second characters are **w** and **ц** for English and Ukrainian respectively, then the service will transform **w** to **ц**.

If you don't want to map a certain character, you can put a space in its position in the other layout. The space character acts as a *don't map this character* command, though it should generally be avoided.

{% hint style="info" %}
This app is "Western-oriented". I developed it specifically to handle switching between Cyrillic and Latin scripts. I don't know how it will work (if at all) with Eastern languages/scripts.
{% endhint %}

## Auto-Configuration

Even though you have to do it only once, configuring character mappings is still cumbersome and error-prone. That's why the app includes the auto-configuration feature. It's available only when all text fields are empty. The auto-configuration is quite simple (naïve even), and it shouldn't be 100% trusted, so you still have to check its output and fix mistakes or add other characters manually. But usually auto-configuration should be good enough.

Here's how the tab looks after running auto-configuration:

![The character mappings tab after auto-configuration](https://3979224463-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fx2tIzR5h95gzWny0Rez6%2Fuploads%2FrVnvRneiYgZpO18DCLMx%2Fv4.1-screen-auto-configuration.png?alt=media\&token=ec6b2b57-2dfe-4ce1-a52a-313c4fe26e3d)

### Windows and macOS

What auto-configuration does on Windows and macOS is basically ask the OS what would happen if certain keys were pressed using various layouts. There is no easy way to get the information about *all* keys on your keyboard, so it asks only about the most common ones. Here's the list of those keys for the US layout:

* All letter keys (<kbd>Q</kbd>, <kbd>W</kbd>, <kbd>E</kbd> etc.)
* Number keys
* Other common keys: <kbd>\[</kbd>, <kbd>]</kbd>, <kbd>;</kbd>, <kbd>'</kbd>, <kbd>,</kbd>, <kbd>.</kbd>, <kbd>/</kbd>, <kbd>\\</kbd>, <kbd>-</kbd>, <kbd>=</kbd>, and <kbd>\`</kbd>
* All those keys with the <kbd>Shift</kbd> key
* All those keys with the <kbd>AltGr</kbd>/<kbd>Option</kbd> key
* All those keys with the <kbd>Shift</kbd>+<kbd>AltGr</kbd>/<kbd>Option</kbd> keys

Not all of those key combinations actually produce characters for all layouts. So, after asking the OS about all of these keys, the app keeps only those character combinations which are defined for all layouts. For example, on Windows if you press <kbd>AltGr</kbd>+<kbd>U</kbd> in the Ukrainian layout, you will get **ґ**, but if you press those keys in the US layout, you won't get anything at all, so the app will just throw **ґ** out as it won't know how to map it to the US layout.

### Linux

Unlike Windows and macOS, there's actually a way to ask the OS (though X11) which characters are produced by all possible key presses. What the app will do is ask about characters produced by all key codes on all shift levels (there are 64 of them!). As with Windows, it will keep only those combinations which are defined for all layouts.

## Limitations

You can map every character only once per layout. Otherwise, it would be impossible to map characters deterministically.

Characters are always mapped one to one. You cannot map one character to several characters.

Dead keys are not supported.

The space character cannot be mapped to other characters. This is not really a limitation, because the space character is the same in every layout (at least that's the assumption).

The app doesn't play nicely with text if you switched the layout yourself in the middle of typing. If that's the case, the app will not switch it correctly, and you will have to fix some of it yourself.


# Preferences

The Preferences tab contains other settings which control the behavior of the Keyboard Switch service. Here's how it looks:

![The preferences tab](https://3979224463-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fx2tIzR5h95gzWny0Rez6%2Fuploads%2FEkrbYIY3JxFFsidFEfBr%2Fv4.1-screen-preferences.png?alt=media\&token=0537451e-d1dc-4970-98c7-6eb9d741b333)

Following is the discussion on the many fields that are in this tab.

## Checkboxes

There are five checkboxes at the top of the Preferences tab:

* Instant switching
* Switch layouts
* Start the service when you log in
* Show a message about uninstalled layouts
* Show the converter

The first checkbox controls whether the Keyboard Switch service should use instant switching or not. The default is yes. The service app needs to access the text to transform it, and for that it uses the clipboard. When instant switching is enabled, the service app will simulate pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> (or <kbd>Command</kbd>+<kbd>C</kbd> on macOS) to copy text into the clipboard. This is why you must first select the text before you let the service app switch it. After transforming the text, the service app will put it back into the clipboard and if the instant switching mode is enabled, it will simulate pressing <kbd>Ctrl</kbd>+<kbd>V</kbd> (or <kbd>Command</kbd>+<kbd>V</kbd> on macOS) to paste the new text instead of the selected text. If you disable this mode, you will have to manually copy the text before switching, and then paste it afterwards. In addition, when this mode is enabled, the app will try to preserve the text that was in clipboard previously and restore it after switching (if the clipboard didn't contain text before switching, e.g., a file or a picture, it won't be restored).

The second checkbox controls whether the service app should switch the layout for you after transforming the text. The default is yes, and there's probably no reason to ever disable it. It just reduces the number of actions you have to do in order to get back on track with typing the text.

The third checkbox lets you control whether the service app will start when you log in. When you open the settings app for the first time, it configures the service app to run at startup automatically.

The fourth checkbox controls whether the settings app should show a warning about uninstalled layouts. If you install a new layout in the system, you should open the settings app and configure it in the Character Mappings tab. If you uninstall a layout, its configuration will still be saved in the app's settings, but it will essentially be redundant – the layout is not present in the system anymore and hence the service app won't need its configuration. When you uninstall a layout and open the settings app, it will show you a warning and a button to delete the unused configuration. If you want to ignore this warning for whatever reason, then uncheck this checkbox.

The fifth checkbox controls whether the converter is visible. Since this is a very niche feature, you will likely never need to use it, so it's hidden by default.

## Switch Settings

You can switch text just by pressing modifier keys. This is similar to switching keyboard layouts in Windows itself – the default key combination to switch layouts in Windows is <kbd>Alt</kbd>+<kbd>Shift</kbd>. You can control which key combination to press to switch text and how many times. The setting contains four fields:

* Modifier keys for switching forward
* Modifier keys for switching backward
* Press count
* Wait time (in milliseconds)

You can select <kbd>Ctrl</kbd>, <kbd>Alt</kbd>/<kbd>Option</kbd>, <kbd>Shift</kbd>*,* and <kbd>Win</kbd> (also known as <kbd>Super</kbd>, <kbd>Meta</kbd>, or <kbd>Command</kbd>), or their combination as modifier keys for switching. The default is <kbd>Ctrl</kbd>+<kbd>Shift</kbd> to switch forward, and <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> (<kbd>Ctrl</kbd>+<kbd>Option</kbd>+<kbd>Shift</kbd> on macOS) to switch backward.

You can also control how many times you should press those modifier keys to switch the text. The default is 2. Max value for this field is 10, but even that is way too much. Min value is 1, but be careful if you set it to 1, because then it would be easy to press it by accident.

Wait time controls how much time the service app waits before deciding that you're not intending on switching text. For example, let's say that the press count is 3, and wait time is 400 ms (which is the default value). You press the key combination. The app then waits for 400 ms to see whether you will press the key combination again. If you don't, then it realizes that you don't want to switch text. If you press the key combination again within this time, the app will then wait again for 400 ms. You then press the key combination for the third time, and the app realizes that you want to switch the text. The min value for this field is 100 ms (which usually makes the app give up waiting much too fast), and the max value for this field is 1000 ms (so, 1 full second, which is usually too slow). 400 ms is the sweet spot, but maybe it won't be for you. You should play around with this setting to figure out which value works best for you.

{% hint style="info" %}
Wait time is ignored if the press count is set to 1.
{% endhint %}


# Converter

The converter lets you manually convert text between arbitrary layouts, not just those installed in your system. In order to enable it, check the *Show the converter* checkbox in the Preferences tab.

{% hint style="info" %}
Converter is a very niche feature. Chances are that you'll never need to use it and never even think of using it, and that's why it's hidden by default. Moreover, it has nothing to do with the main functionality of the app – switching text in the background. Feel free to skip this article if you're not interested.
{% endhint %}

## The Converter Functionality

Here's how the Converter tab looks (when it's configured):

![The converter tab](https://3979224463-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fx2tIzR5h95gzWny0Rez6%2Fuploads%2F2RgPwEpVMq1LmZcGMSmy%2Fv4.1-screen-converter.png?alt=media\&token=bad3b7d5-9fc5-404d-a34e-4e0aea97b46e)

The tab consists of two main parts:

* Text area
* Configuration area

Text area is where you input text and get the output. Quite straightforward.

Configuration area is where you configure how to switch the text. You can select the source layout and the target layout and do the actual switching or clearing of the output.

Custom layouts are configured in the Converter Settings tab, discussed in the next section.

{% hint style="info" %}
At least two custom layouts are required to enable the converter.
{% endhint %}

## Converter Settings

The Converter Settings tab lets you configure custom layouts for the converter. Here's how it looks:

![The converter settings tab](https://3979224463-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fx2tIzR5h95gzWny0Rez6%2Fuploads%2F4coVZK0WbIZJgiRVu3Vw%2Fv4.1-screen-converter-settings-main.png?alt=media\&token=c1e4cb5a-5c91-4ce2-a047-90fd1c2e3633)

It's pretty similar to the Character Mappings tab, and the way configuration of characters works is identical. The main difference is that you can control what's shown here. You can add layouts, remove, or rename them. You can't change the order of the layouts, but it doesn't actually matter here. You can't have two or more layouts with the same name.

Just like with Character Mappings, you can auto-configure custom layouts, but here you have to select layouts to configure first. This is available only on Windows though. Here's how the settings for auto-configuration look:

![The settings for converter auto-configuration](https://3979224463-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fx2tIzR5h95gzWny0Rez6%2Fuploads%2Fqb4UFHiVv7YczDJoHK0v%2Fv4.1-screen-converter-settings-config.png?alt=media\&token=1c28d527-3872-4796-8c20-5d3843b80570)

You can select layouts using the drop-down. It includes all keyboard layouts that you can choose in Windows. After you selected the layouts, and clicked *Save*, the app will load those layouts into Windows, execute the same auto-configuration algorithm as it does in the Character Mappings tab, and then unload those layouts from the system.

{% hint style="info" %}
It's best to auto-configure all layouts you want to add at once. If you auto-configure them one by one, then some characters may not be mapped correctly since auto-configuration will remove mappings which are not defined in *all* layouts.
{% endhint %}

## Why the Converter Was Added

Now that you know what the converter does, you'll agree that its use is extremely limited. And to be honest, the reason I've added it is not usability, it's sentimentality. A very long time ago, when the idea that there should be a way to easily switch mistyped text first occurred to me, I created an app (simply called Converter) which did just that, but it didn't do it in the background. You had to enter text in a window much the same way you have to do it in the converter in this app. It was actually one of the first usable apps that I have ever created. And this app even helped me out once, when I had to use a computer abroad and it didn't have the Ukrainian layout installed. So, after releasing version 2 of this app in 2018 I thought that it would be nice to add the converter feature to the next release even though it will probably not be used by anybody (not even me). In addition, I've learned a couple interesting things about how keyboard layouts work in Windows when I implemented this feature. So here we are.


# Other Tabs

Other tabs in the settings app include the Sandbox tab and the About tab.

## Sandbox

Sandbox is absurdly simple – it's just a text box. That's it! Here's how it looks:

![The sandbox tab](https://3979224463-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fx2tIzR5h95gzWny0Rez6%2Fuploads%2F9ifduJ5Bqgh3F26x9Q5i%2Fv4.1-screen-sandbox.png?alt=media\&token=affb35c5-c0a9-409a-b3d4-476b991e01ef)

Sandbox lets you play around with switching text when you change the app's settings. It contains no logic whatsoever. It's literally just a text box.

## About

The About tab contains some general info about the app. Here's how it looks:

![The about tab](https://3979224463-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fx2tIzR5h95gzWny0Rez6%2Fuploads%2FSSxDaAXBpUFEUzihjBh4%2Fv4.1-screen-about.png?alt=media\&token=0998f27f-d0dc-4ec4-8778-09b925a0390e)

If you want more info, you can view the docs (these very pages).

You can also check whether updates for the app are available. If they are indeed available, then you can go to the releases page on GitHub to get them. The app doesn't support auto-updating, so you will have to install a newer version yourself. Remember that you have to stop the service app before installing a newer version.

That's it for the settings app. If you want technical info about Keyboard Switch, you can check out the next articles.


# Command Line Interface

The Keyboard Switch service app has a CLI which you can use to control it. On Windows, it's not really convenient as GUI apps cannot output anything to the console, but it can be used as well.

The name of the executable is `KeyboardSwitch`. This article will assume it's installed on Linux in the `/opt/keyboard-switch` directory. On macOS, it's located in the `/opt/Keyboard Switch.app/Contents/MacOS` directory.

## Commands

### Running the App

To start Keyboard Switch, simply run it in the terminal:

```
/opt/keyboard-switch/KeyboardSwitch &
```

The `&` makes the service app run in the background. On Windows, the `&` is not needed as GUI apps always run separately from the terminal.

Keyboard Switch is a single-instance app. If one instance is already running, and you start another one, it will immediately silently exit.

The app will exit immediately if it cannot find the settings file. This file is created when you run the settings app for the first time. This is done so that there's a lower chance that this app will run in an unconfigured state.

### Stopping the App

To stop Keyboard Switch, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --stop
```

If an instance of Keyboard Switch is running, this command will stop it. If no instance is running, it will do nothing.

### Reloading the Settings

To reload the settings of Keyboard Switch, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --reload-settings
```

If an instance of Keyboard Switch is running, this command will make it invalidate its current settings and reload them. If no instance is running, it will do nothing.

### Checking Whether the App Is Running

To check whether Keyboard Switch is running, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --check
```

If an instance of Keyboard Switch is running, this command will output `KeyboardSwitch is running`. Otherwise, it will output `KeyboardSwitch is not running`.

### Showing a Help Message

To show the help message, run either of the following:

```
/opt/keyboard-switch/KeyboardSwitch --help
/opt/keyboard-switch/KeyboardSwitch -?
```

### Command Formats

The aforementioned commands can be prefixed with `--`, `-`, or `/`. For example, to stop Keyboard Switch, you can specify `stop`, `-stop`, `--stop`, or `/stop`.

## Exit Codes

The following exit codes are available:

* `0` – The app has exited successfully.
* `1` – An unspecified error has occurred.
* `2` – The app cannot run, because its settings have an incompatible version. The app is backward-compatible with respect to settings versions – it will read the settings created by an older version and modify them to fit the current version. But it's not forward-compatible – version 4.1 will not work if the settings were created or updated by a newer version.
* `3` – `stop`, `reload-settings`, or `check` was specified as the command, but no instance of Keyboard Switch is running.
* `4` – An invalid command was specified.
* `5` – The settings file was not found.
* `6` – The app doesn't have access to the accessibility API on macOS.


# Technical Stuff

Keyboard Switch is written using [C#](https://github.com/dotnet/csharplang) and [.NET 6](https://dotnet.microsoft.com/download/dotnet/6.0). Following is the list of technologies used in this app and some other technical aspects.

## UI

The Keyboard Switch Settings app is written using [Avalonia](https://avaloniaui.net), a cross-platform UI framework for .NET. I chose it because unlike other UI frameworks for .NET, it's cross-platform, and I had to do literally nothing for it to work on macOS and Linux as well. The style is provided by [FluentAvalonia](https://github.com/amwx/FluentAvalonia).

Previous versions of the app used .NET Framework and WPF. Back then I didn't expect to have it working on different platforms.

Previous versions of the app also included a tray icon so you could see that the app is running. I removed it in version 3.0 as I don't see much value in keeping it and cluttering your tray.

## Core Logic

### Windows

The service app is just an app which runs in the background. I could have made it into a Windows service, but decided against it when I read somewhere that Windows services cannot set up keyboard hooks. I didn't actually verify this info, so I'm not sure it's correct, but the background app approach works just fine, so it's likely to stay this way.

The service app calls various native functions from the Windows' *user32.dll*. It uses [Vanara](https://github.com/dahall/Vanara) to call them.

In the previous versions (up to 3.0) the service and the settings app were not separated. It was just an app running with a hidden window which showed up when you opened it. Having a hidden window always loaded is not that great of an idea, even though it used very little RAM.

### macOS

On macOS, the service app runs as a *launchd* service. *launchd* provides the ability to start at login. The settings app starts the service app through *launchd* as well. macOS 10.11+ is required since it contained some major changes in *launchd*.

The service app uses multiple native macOS frameworks:

* *CoreFoundation* – for low-level string, array, and pointer manipulation.
* *CarbonCore* (part of *CoreFoundation*) – for translating key codes with layout info into Unicode characters.
* *CoreGraphics* – for simulating keyboard events.
* *HIToolbox* – for working with keyboard layouts.
* *AppKit* – for working with the clipboard.

It uses functions and constants from these frameworks using P/Invoke directly, except for *AppKit* – that one is called by the [TextCopy](https://github.com/CopyText/TextCopy) library which the app uses for copying and pasting text.

### Linux

At first, I decided to run the app as a *systemd* service, but it proved not to provide much value, so I've since reverted this decision.

The service app uses X11, especially the X Keyboard Extension, and the X Test Extension. Currently it doesn't work on Wayland, even through XWayland. It calls various native Xlib functions using P/Invoke directly.

The app also uses Bash and [xsel](https://github.com/kfish/xsel), but those are not used directly – rather they are used by [TextCopy](https://github.com/CopyText/TextCopy).

If the Linux desktop environment is GNOME then the app switches layouts a little differently than in other DEs. GNOME doesn't let apps switch layouts using X11 directly – it will immediately switch it back. Instead, the app installers also add a small GNOME Shell extension (which is simply called Switch Layout) and the app switches layouts through it. GNOME should be made aware of this extension after installation; hence you should restart it after installing the app. If you don't then the app will still work but won't be able to switch layouts until you log out or reboot.

### The Settings App

The core logic of the settings app is implemented using [ReactiveUI](https://www.reactiveui.net) as the MVVM framework. Also, [Splat](https://github.com/reactiveui/splat) is used for service location.

## App Structure

Keyboard Switch's files are located in the same directory on Windows and Linux – and there are a bunch of them since these are two self-contained .NET applications. The apps could be published as single-file applications, but they share quite a bit of libraries, so these libraries would be duplicated for both apps.

On macOS, the two applications are located in separate directories – this is done because on macOS, every application should be contained inside a bundle. The apps are published as single-file apps for that platform as the shared libraries would have to be duplicated either way.

## The Global Keyboard Hook

The app uses [libuiohook](https://github.com/kwhat/libuiohook) to create a global keyboard hook. The library is cross-platform and supports almost all popular OSes and architectures. Since this library is native and it's non-trivial to build, I've developed a .NET wrapper for it, [SharpHook](https://github.com/TolikPylypchuk/SharpHook), so that I don't have to deal with a native library in this project.

Previously, the app used a Windows keyboard hook directly, but that doesn't work on other systems.

## Preferences

Preferences are stored in the user's local app data folder (under the *KeyboardSwitch* directory) on Windows. I didn't put it into the normal app data folder because that one is shared if you use the same Windows account on multiple machines, and that kind of defeats the purpose of this app being configured for each machine individually.

On macOS and Linux, the settings are stored in the *\~/.keyboard-switch* directory.

This app uses [Akavache](https://github.com/reactiveui/Akavache) as the engine for storing settings.

## Logging

This app uses a plain-text log file to log the stuff it’s doing and errors it encounters along the way. [Serilog](https://serilog.net) is used as the logging library. The log file is stored in the same folder as the preferences and is rolled over after reaching 10 MB. If you really want to (and know how), you can change the logging configuration in the *appsettings.json* file. On Windows and Linux, this file is located in the same folder as the app itself. On macOS, this file is located in the bundle's resources folder, and you probably shouldn't change it as it may break the bundle's signature (though I'm not sure about that).

## Tests

There are none. Honestly, I don't even know how to approach testing, because the core logic of the app is essentially creating system-wide side effects, so don't think it's really testable. As for the settings app, well, I could test it, but that would take a lot of time, and the app is pretty simple, so I don't plan on doing it in the nearest future.

## Docs

The docs are built and hosted on [GitBook](https://www.gitbook.com).

Previously these articles were built using [Jekyll](https://jekyllrb.com) and hosted on [GitHub Pages](https://pages.github.com), and used the [Minimal Mistakes theme](https://mmistakes.github.io/minimal-mistakes).

## Building from Source

You can build Keyboard Switch from source if you like. All projects (except the Windows installer) require .NET 6.

### The Projects

The app consists of 8 projects:

* *KeyboardSwitch*: The Keyboard Switch service itself
* *KeyboardSwitch.Core*: Core functionality and interfaces for the projects
* *KeyboardSwitch.Settings*: The Keyboard Switch Settings app
* *KeyboardSwitch.Settings.Core*: The core logic of the settings app
* *KeyboardSwitch.Windows*: The implementation of the core functionality for the Windows platform
* *KeyboardSwitch.MacOS*: The implementation of the core functionality for the macOS platform
* *KeyboardSwitch.Linux*: The implementation of the core functionality for the Linux platform
* *KeyboardSwitch.Windows.Setup*: The setup project

### Building the App Itself

Building the service app and the settings app is quite straightforward.

On Windows, you can simply use the *Build-Portable.ps1* script located in the *build/windows* directory. Bear in mind that you have to call this script from the solution root directory: `.\build\windows\Build-Portable.ps1`. It will create the *KeyboardSwitch-Portable.zip* file in the *bin* directory which you can then unpack into wherever you like.

On macOS, building the app is not as easy as for other platforms since it requires Apple Developer certificates. You should have two certificates inside your Keychain: Apple Developer ID Application, and Apple Developer ID Installer. You can run the *build-pkg.sh* script from the solution root: `./build/macos/build-pkg.sh`, but it expects certificate names and Apple ID/Team ID as environment variables. To build the uninstaller package, you can run the *build-uninstaller-pkg.sh* script from the solution root as well: `./build/macos/build-uninstaller-pkg.sh`. It also expects the installer certificate to be present.

On Linux, you should use the *build-tar.sh* script to build the tar.gz file, the *build-deb.sh* script to build the deb package, and the *build-rpm.sh* script to build the RPM package. They are located in the *build/tar*, *build/deb*, and *build/rpm* directories respectively. As with the Windows script, you have to execute these scripts from the solution root: `./build/tar/build-tar.sh`, `./build/deb/build-deb.sh`, and `./build/rpm/build-rpm.sh`. The scripts' results will be in the *bin* directory.

Alternatively, you can build the projects using Visual Studio 2019 or later, or with the `dotnet` tool. Note however that you have to build the whole solution. The startup project is *KeyboardSwitch.Settings*, and if you build it, it won't actually build the *KeyboardSwitch* project, because the settings app doesn't directly depend on the service app.

All projects (except the installer) are built into a shared *bin* folder located in the solution root. Again, this is because the settings app needs the service app to be in the same folder, but the projects don't depend on each other.

It's better to use `dotnet publish` than simply using the raw build results. You can look into how the build scripts call `dotnet publish`.

The installer project is excluded from the solution build sequence as it's not always needed.

### Building the Windows Installer

If you want to properly install the app on Windows, you can build the installer. Unlike the other projects, this one requires .NET Framework 4.8. This is because it's built with [WixSharp](https://github.com/oleg-shilo/wixsharp), which in turn is based on [the WiX toolset](https://wixtoolset.org), and as of version 3.11.2, WiX doesn't support .NET 6.

Simply run the build, and it will generate the MSI installer in the project's *bin* folder. Before the build, it calls `dotnet publish` to use its output.

You'll have to build the installer from source if you want to get a Windows installer for Arm64, but there are some changes that you need to make. Firstly, you should get WiX 3.14 – it's still in development as of the time of this writing, so it's not recommended for production. Secondly, edit the *KeyboardSwitch.Windows.Setup.csproj* file and set the `Arch` property to be `arm64`. Now you can build the installer for Arm64.


# About

Keyboard Switch. Version 4.1. Created by [Tolik Pylypchuk](https://github.com/TolikPylypchuk).

## Acknowledgements

The UI for the settings app was created using [Avalonia](https://avaloniaui.net) with [ReactiveUI](https://www.reactiveui.net) and [FluentAvalonia](https://github.com/amwx/FluentAvalonia). The global keyboard hook is implemented using [libuiohook](https://github.com/kwhat/libuiohook). Windows installer created with [WixSharp](https://github.com/oleg-shilo/wixsharp). Docs are built using [GitBook](https://www.gitbook.com). Icon made by [Smashicons](https://smashicons.com) from [www.flaticon.com](https://www.flaticon.com).

## Changelog

### [v4.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.1) (10 February 2022)

* The app now works on macOS
* The app now supports Arm64 in addition to x64 (but the support is experimental for Windows and Linux)
* The app now switches layouts using native methods on Linux, hence layout settings are not needed anymore
* On Windows switching backward works correctly when there are more than two layouts
* The settings app will configure the service app to run at login when opened for the first time, instead of installers doing that – this means that the service app will be configured correctly for all users
* Windows Installer can delete all users' configurations when uninstalling the app

This is the first minor release which contains new features instead of just bug fixes, and it's a big one at that.

### [v4.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.0) (28 November 2021)

* The app now works on Linux (via X11 only; Wayland is not supported)
* The legacy hot-key mode was removed – only the modifier keys mode is available
* The UI theme is overhauled
* The converter is hidden by default
* .NET 6 is used instead of .NET Core 3.1
* The app's performance was improved, though it's still not ideal

This is the first major version of the app which is not completely rewritten, though it was significantly changed. From now on, most changes (like macOS support) will come as minor versions, and version 4 will be the major version for the foreseeable future.

### [v3.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v3.0) (4 August 2020)

* A completely rewritten app based on .NET Core and working as a truly UI-less app instead of an app with a hidden window
* The settings are now a separate app written with Avalonia instead of WPF
* Tray icon was removed
* Added the ability to switch between multiple layouts of the same language (e.g. QWERTY and Dvorak for English)
* Instant switching mode is not experimental anymore and enabled by default
* Added the ability to auto-configure character mappings
* Added checking for updates

### [v2.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v2.1) (1 April 2018)

Minor bug fixes

### [v2.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v2.0) (13 January 2018)

* Brand new installer for the app
* Instant switching mode
* Updated readme
* Updated configuration
* Minor UI updates
* Minor bug fixes

### [v1.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v1.1) (somewhere in 2015)

Minor bug fixes

### v1.0 (somewhere in 2015)

All the basic functionality:

* Switching text
* Starting at system startup
* Tray icon

## License

MIT License

Copyright (c) 2015 Anatoliy Pylypchuk

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


# Keyboard Switch

Welcome to the Keyboard Switch docs!

Keyboard Switch is an application which switches typed text as if it were typed with another keyboard layout.

If you ever write some text and then realize that you have written it using a wrong layout, you don't have to delete it and start over anymore. Just select the text, press a magic key combination, and that's it!

I hope this app will make your life at least 1% easier :)

{% hint style="info" %}
If you're using version 4.0, then you should upgrade to version 4.3 as soon as possible since it contains several improvements and bug fixes.
{% endhint %}

## Quick Start

### Windows

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.msi* file and run it to install the app.

After installation, the Keyboard Switch Settings app will start. It may take some time as the app will do some initial setup. If it doesn't start for some reason, then find it in the list of your apps.

In the opened app, press the *Auto-configure* button.

Press *Save*.

Press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text, and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> twice instead.

### Linux

The app is available as a deb package (for Debian-based distributions, such as Ubuntu, Mint etc.), an RPM package (for RHEL-based distributions, like CentOS or Fedora, as well as SUSE), and a simple *tar.gz* file. You can get these files from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

{% hint style="info" %}
If you're using an RPM package, there are a couple things to note before installing the app (which you can find in the [installation](/4.0/usage-guides/installation#installing-the-app) article).
{% endhint %}

Bear in mind that KeyboardSwitch only works on X11 – it won't work on Wayland (even with XWayland apparently).

If you use the deb or RPM package, then simply install it either by double-clicking on it, or through the terminal. If you use the *tar.gz* file, then the set-up is not quite as quick, so you can read about it in the [installation page](/4.0/usage-guides/installation#installing-the-app).

After installing the app, open Keyboard Switch Settings – it should appear in the list of your apps.

In the opened app, press the *Auto-configure* button.

Press *Save*.

Press *Start*.

That's it! You're ready to use Keyboard Switch in its basic configuration. There's a big chance you won't need to configure it further. But if you do, then all the info you'll ever need is provided in these docs.

To switch text forward, select the text and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice. To switch it backward, press <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> twice instead.

## How the App Works

The app is composed of two parts: the Keyboard Switch service and the Keyboard Switch Settings app. The service always runs in the background (and starts when you log into the system) and listens to key presses. When you press the magic key combination, it reacts by copying the selected text, transforming it, and pasting it for you. The settings app is used for configuring the service and for starting/stopping it manually.

Here are the basic steps you should take to switch the text:

* Type some text using an incorrect layout
* Realize your mistake
* Select the text (you can press <kbd>Ctrl</kbd>+<kbd>A</kbd> to select all text)
* Press the magic key combination (the default is pressing <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice)
* Profit

The app uses the clipboard to get the text to transform and then puts the transformed text back into the clipboard. The app will try to preserve the text that was in the clipboard before switching and restoring it afterwards. It doesn't guarantee that the text will be restored though. Also, any non-text data (e.g., a file or a picture) will not be restored.

{% hint style="info" %}
The app simulates pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> to copy and <kbd>Ctrl</kbd>+`V` to paste text. This is the default behavior for most (if not all) applications. But if you are working in an app which behaves differently on those key presses, this app will not be able to instantly switch text. You can disable this behavior and copy/paste the text manually.
{% endhint %}

## Supported Platforms

Keyboard Switch currently works on Windows 10/11 and on Linux via X11. It can probably work on older versions of Windows as well, but I'm not going to support them. As for Linux, it needs several prerequisites to run (more on that on [the installation page](/4.0/usage-guides/installation#linux)).

Only the x64 architecture is supported. Arm64 is supported starting from version 4.2.

## Layouts

The app uses the list of your layouts in the same order as defined by the system. You can switch both forward and backward through this list. The app also automatically changes your layouts, so you don't have to do it yourself. You can disable this as well if you so wish. You cannot add a layout that's not present as one of the system's layouts. If you add/remove a layout while the app is running, you'll have to configure it in the settings and restart the service.

{% hint style="info" %}
This app is "Western-oriented". I developed it specifically to handle switching between Cyrillic and Latin scripts. I don't know how it will work (if at all) with Eastern languages/scripts.
{% endhint %}


# Installation

## Windows

### Using a Windows Installer

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.msi* file and run it to install the app.

After installing the app, the installer will run the settings app. Currently it's not really optimized, so the startup time is not perfect; it can take a couple seconds for the app to get started. On the first start-up the settings app will configure the service to run when you log into the system.

If multiple users use the PC, then bear in mind that the app configures itself to run on log-in only for the user that installed the app. Other users have to configure it manually.

When the settings app starts up you should configure the character mappings (you can read more about it in the next article). After you have configured the character mappings and possibly some other preferences, start the app using the *Start* button at the bottom of the window. That's it! Now you're ready to use the Keyboard Switch service.

### Uninstalling the App

You can uninstall the app using the Settings app just like you would uninstall any other app.

{% hint style="warning" %}
The installer will not delete the registry entry which says that your app should start when you log in. If you want to keep your registry clean, you have to disable it in the settings app before uninstalling it.
{% endhint %}

Upon uninstallation the installer will ask whether you want to delete the app's configuration as well. If you choose not to delete the configuration, you can delete it later manually at any other time. It's stored under the user's local app data folder.

{% hint style="warning" %}
The installer will only delete the current user's configuration. If there are other users on the PC, they will have to delete the configuration manually.
{% endhint %}

### Using the Portable Version

If you don't want to install the app (or can't), you can use the portable version of the app. It's literally the same as the installable version; there are no differences. Again, go to the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases) and download *KeyboardSwitch-4.1-x64-win.zip*. Extract the archive to anywhere you want and start *KeyboardSwitchSettings.exe*. You can configure the app to run when you log in just like the installed version. The configuration for the portable version is also stored under the user's local app data folder.

## Linux

### Installing the App

#### Prerequisites

There are several prerequisites for running the app on Linux:

* X11
* X Keyboard Extension (XKB) which is enabled by default
* X Test Extension – used to simulate pressing keys like <kbd>Ctrl</kbd>+<kbd>C</kbd> and <kbd>Ctrl</kbd>+<kbd>V</kbd> for you
* [xsel](https://github.com/kfish/xsel) – used to copy and paste text
* Bash – used to call xsel, but you don't need to have it as your default shell
* Freedesktop conventions – used to make the service app start when you log in, and to make the settings app appear in the list of your installed apps (not required for the app itself though)

Keyboard Switch doesn't support Wayland (even with XWayland).

The most popular desktop systems (at least GNOME, KDE Plasma, Xfce, and LXQt) all adhere to the Freedesktop protocols, so the last prerequisite is automatically available, unless you're running a very unusual setup.

[Click here](https://github.com/TolikPylypchuk/KeyboardSwitch/issues/59) to see the list of Linux distributions on which the app was tested.

#### Using a Deb Package

If you're running a Debian-based distribution (e.g., Ubuntu or Mint), then you can install Keyboard Switch using a deb package. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

The package takes care of xsel and the X Test extension, so you don't need to install them yourself.

After installation, the settings app will be available in the list of installed apps, and the service app will be configured to run at login (it will be configured for all users though).

#### Using an RPM Package

If you're running a RHEL-based distribution (e.g., CentOS or Fedora), or SUSE, then you can install KeyboardSwitch using an RPM package. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases).

The package takes care of xsel and the X Test extension, so you don't need to install them yourself.

{% hint style="info" %}
If you're using RHEL, CentOS, or Rocky Linux, then make sure that the EPEL repository is installed before installing Keyboard Switch. Otherwise, it won't be able to install xsel.
{% endhint %}

{% hint style="info" %}
SUSE may complain that it cannot find libXtst when installing the app using the RPM package. This is because the package is targeted for RHEL and derivatives. You can ignore this warning and proceed with installation, but make sure that libXtst6 is installed before starting the app.
{% endhint %}

After installation, the settings app will be available in the list of installed apps, and the service app will be configured to run at login (it will be configured for all users though).

#### Using a Tar Archive

Keyboard Switch is also available as a *tar.gz* fie. You can get it from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). You can then extract it to anywhere you like (e.g., into the */opt* directory). The deployed app includes two scripts – *install.sh* and *uninstall.sh*. *install.sh* configures Freedesktop to start the KeyboardSwitch service when you log in and to add the settings app to the list of installed apps. *uninstall.sh* deletes this configuration.

Here are the steps required for installing the app on Debian, Ubuntu, Linux Mint, etc.:

```
sudo apt update
sudo apt install xsel libxtst6  # Install xsel and the X Test Extension
tar -xzf keyboard-switch-4.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
sudo chmod 755 install.sh uninstall.sh  # Let every user use the app
./install.sh
```

Here are the steps required for installing the app on RHEL, CentOS, Fedora, or Rocky Linux (use `yum` instead of `dnf` on older systems):

```
sudo dnf install epel-release  # Add the EPEL repository (not needed for Fedora)
sudo dnf install xsel          # Install xsel
sudo dnf install libXtst       # Install the X Test Extension
tar -xzf keyboard-switch-4.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
sudo chmod 755 install.sh uninstall.sh  # Let every user use the app
./install.sh
```

Here are the steps required for installing the app on SUSE (you may need to add the X11:XOrg repository to install libXtst6):

```
sudo zypper install xsel      # Install xsel
sudo zypper install libXtst6  # Install the X Test Extension
tar -xzf keyboard-switch-4.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
sudo chmod 755 install.sh uninstall.sh  # Let every user use the app
./install.sh
```

Here are the steps required for installing the app on Arch Linux:

```
sudo pacman -S xsel     # Install xsel
sudo pacman -S libxtst  # Install the X Test Extension
tar -xzf keyboard-switch-4.0-x64.tar.gz -C /opt
cd /opt/keyboard-switch
sudo chmod 755 install.sh uninstall.sh  # Let every user use the app
./install.sh
```

### Uninstalling the App

For the deb and RPM packages, it's simple – just uninstall the package. For the *tar.gz* file, run the included *uninstall.sh* script, and delete the app's directory. If you want to delete the app's configuration as well, then delete the *\~/.keyboard-switch* directory.


# The Settings App

Keyboard Switch Settings is a simple app which controls the behavior of the Keyboard Switch service. You can find the app in the list of your installed apps (e.g. the Start menu on Windows). Here's how it looks:

![](https://2323494160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQRd6i8Vkkjc7Ss7rkN-1834917677%2Fuploads%2FKdlxOSs7oGIb4QPgg8Vi%2Fv4.0-screen-char-mappings.png?alt=media\&token=3749f11d-c5eb-42ca-a4a4-5df6b910ba1b)

The app is composed of six tabs:

* Character mappings: contains the settings which tell Keyboard Switch how to transform characters between layouts
* Preferences: contains other settings
* Converter: lets you manually convert text between arbitrary custom layouts (hidden by default)
* Converter settings: contains the list of custom layouts for the converter (hidden by default)
* Sandbox: lets you play around with switching the text
* About: contains info about the app

At the bottom there's a strip with the status of the Keyboard Switch service. If it's not running, you can press the *Start* button to start it manually (although usually you wouldn't do that because the service will start when you log in). If the service is running, you can stop it by pressing the *Stop* button. It won't actually kill it – it will send a *stop* command, and the service will do some clean-up and stop on its own. If it's taking a long time to stop, it may mean that something went wrong. In that case you can force it to stop by pressing the *Kill* button.

{% hint style="info" %}
If you change anything in the settings app, you can save it or cancel it. When you save it, the settings app sends a notification to the service app (if it's running) about changes in configuration, so you don't have to restart the service after saving.
{% endhint %}

The following articles describe each tab of the settings app in more detail.


# Character Mappings

In order for the Keyboard Switch service to know how to map characters, you have to configure the character mappings yourself. The app reads the list of installed layouts in the system, so it knows which layouts you use and in what order. What it doesn't (and can't) know is the physical layout of your keyboard, so it doesn't know what happens if you press certain keys on your keyboard.

## Text vs Keyboard

This section explains *why* you need to configure character mappings for the app. If you're not interested, feel free to skip it.

Working with text and working with keyboard are two wildly different things. You, the user of a computer, usually work with a keyboard (or other input devices, but those don't matter here). This app however works with text (even though its name might suggest differently), and so text transformation during switching will most probably not be perfect.

Ideally you wouldn't have to configure the app at all – it would just know how to transform the text you mistyped into another layout. After all, the OS somehow knows which characters to produce when you press various keys. But going that way would be extremely difficult, if not impossible.

Firstly, pressing keys and entering characters are absolutely not the same thing. Many keys don't have corresponding characters at all, like <kbd>Ctrl</kbd> or <kbd>Page Up</kbd>. The same key press can produce different characters based on the state of other keys. For example, the <kbd>A</kbd> key usually produces **a**, but when <kbd>Shift</kbd> is down, the key produces **A**. And then there are dead keys – key combinations that produce one character by pressing two (or even three) keys. For example, in the US International layout, pressing <kbd>'</kbd> and then <kbd>A</kbd> will produce **á**.

Secondly, it's impossible to know which keys have been pressed just by looking at text. This is because the same character can be produced using different keys or key combinations (or it can be pasted, so the keyboard wouldn't be used at all).

So, in order to just know how to transform the text you've mistyped, the app would have to keep track of the keys you've pressed and then infer which of those pressed keys actually played a role in producing the mistyped text and then ask the OS which characters would be produced with the same key sequence. You can see how that's unreasonable. First of all, the app would have to track *all* the keys you press, and that would be quite sketchy. Would you trust an app which logs everything you type? I certainly wouldn't. And ethics aside, there still are technical issues. How many keys should the app track? What happens if the user pastes part of the text instead of typing it? Etc., etc.

And that's why the app uses a much simpler solution – it lets you, the user, figure out how the text should be transformed. The app can auto-configure the mappings using a simple method, but it's still up to you to check whether it's all correct.

## How Character Mappings Work

Here's how the tab looks when the app is opened for the first time:

![The character mappings tab when the configuration is empty](https://2323494160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQRd6i8Vkkjc7Ss7rkN-1834917677%2Fuploads%2FBuXAQfUIqNy5P8zdSTIE%2Fv4.0-screen-char-mappings-empty.png?alt=media\&token=2eb93ab5-3655-48a9-919f-a778089b102f)

You have to enter every character you can think of (which can be entered using your keyboard) into the text fields which correspond to layouts. For example, press the <kbd>Q</kbd> key, then press the <kbd>W</kbd> key, and so on. Then press <kbd>Shift</kbd>+<kbd>Q</kbd>, then <kbd>Shift</kbd>+<kbd>W</kbd> etc. to add uppercase letters.

You should press the keys *in the same order* for all layouts. Order matters here because the service will look at characters in same positions to determine how to transform the text. For example, let's say you have two layouts in your system: English (US) and Ukrainian (Enhanced). You put **q** as the first character in the text field for English, and **й** as the first character in the text field for Ukrainian (because that's the character you get when you press the <kbd>Q</kbd> key). Now the service will know that when it switches from English to Ukrainian, it should transform **q** to **й**. If the second characters are **w** and **ц** for English and Ukrainian respectively, then the service will transform **w** to **ц**.

If you don't want to map a certain character, you can put a space in its position in the other layout. The space character acts as a *don't map this character* command, though it should generally be avoided.

## Auto-Configuration

Even though you have to do it only once, configuring character mappings is still cumbersome and error-prone. That's why the app includes the auto-configuration feature. It's available only when all text fields are empty. The auto-configuration is quite simple (naïve even), and it shouldn't be 100% trusted, so you still have to check its output and fix mistakes or add other characters manually. But usually auto-configuration should be good enough.

Here's how the tab looks after running auto-configuration:

![The character mappings tab after auto-configuration](https://2323494160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQRd6i8Vkkjc7Ss7rkN-1834917677%2Fuploads%2FdgGfEvpmJ9Sgst1BlddQ%2Fv4.0-screen-auto-configuration.png?alt=media\&token=ec841f70-f231-4f6a-a238-f0ac05b383dc)

### Windows

What auto-configuration does on Windows is basically ask the OS what would happen if certain keys were pressed using various layouts. There is no easy way to get the information about *all* keys on your keyboard, so it asks only about the most common ones. Here's the list of those keys for the US layout:

* All letter keys (<kbd>Q</kbd>, <kbd>W</kbd>, <kbd>E</kbd> etc.)
* Number keys
* Other common keys: <kbd>\[</kbd>, <kbd>]</kbd>, <kbd>;</kbd>, <kbd>'</kbd>, <kbd>,</kbd>, <kbd>.</kbd>, <kbd>/</kbd>, <kbd>\\</kbd>, <kbd>-</kbd>, <kbd>=</kbd>, and <kbd>\`</kbd>
* All those keys with the <kbd>Shift</kbd> key
* All those keys with the <kbd>AltGr</kbd> key
* All those keys with the <kbd>Shift</kbd>+<kbd>AltGr</kbd> keys

Not all of those key combinations actually produce characters for all layouts. So after asking the OS about all of these keys, the app keeps only those character combinations which are defined for all layouts. For example, if you press <kbd>AltGr</kbd>+<kbd>U</kbd> in the Ukrainian layout, you will get **ґ**, but if you press those keys in the US layout, you won't get anything at all, so the app will just throw **ґ** out as it won't know how to map it to the US layout.

### Linux

Unlike Windows, there's actually a way to ask the OS (though X11) which characters are produced by all possible key presses. What the app will do is ask about characters produced by all key codes on all shift levels (there are 64 of them!). As with Windows, it will keep only those combinations which are defined for all layouts.

## Limitations

You can map every character only once per layout. Otherwise, it would be impossible to map characters deterministically.

Characters are always mapped one to one. You cannot map one character to several characters.

Dead keys are not supported.

The space character cannot be mapped to other characters. This is not really a limitation, because the space character is the same in every layout (at least that's the assumption).

The app doesn't play nicely with text if you switched the layout yourself in the middle of typing. If that's the case, the app will not switch it correctly, and you will have to fix some of it yourself.


# Preferences

The Preferences tab contains other settings which control the behavior of the Keyboard Switch service. Here's how it looks:

![The preferences tab](https://2323494160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQRd6i8Vkkjc7Ss7rkN-1834917677%2Fuploads%2FZcNcBC7mFlbD7gRG7sLi%2Fv4.0-screen-preferences.png?alt=media\&token=886fdbd4-8408-4153-8171-0702ded09a02)

Following is the discussion on the many fields that are in this tab.

## Checkboxes

There are five checkboxes at the top of the Preferences tab:

* Instant switching
* Switch layouts
* Start the service when you log in
* Show a message about uninstalled layouts
* Show the converter

The first checkbox controls whether the Keyboard Switch service should use instant switching or not. The default is yes. The service app needs to access the text to transform it, and for that it uses the clipboard. When instant switching is enabled, the service app will simulate pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> to copy text into the clipboard. This is why you must first select the text before you let the service app switch it. After transforming the text, the service app will put it back into the clipboard and if the instant switching mode is enabled, it will simulate pressing <kbd>Ctrl</kbd>+<kbd>V</kbd> to paste the new text instead of the selected text. If you disable this mode, you will have to manually copy the text before switching and then paste it afterwards. In addition, when this mode is enabled, the app will try to preserve the text that was in clipboard previously and restore it after switching (if the clipboard didn't contain text before switching, e.g., a file or a picture, it won't be restored).

The second checkbox controls whether the service app should switch the layout for you after transforming the text. The default is yes, and there's probably no reason to ever disable it. It just reduces the number of actions you have to do in order to get back on track with typing the text.

The third checkbox lets you control whether the service app will start when you log in. On Windows, the default is yes if you installed the app using a Windows installer, and no if you're using the portable version. On Linux, the default is yes if you installed the deb package, or ran the *install.sh* script bundled with the *tar.gz* archive, and no otherwise.

The fourth checkbox controls whether the settings app should show a warning about uninstalled layouts. If you install a new layout in the system, you should open the settings app and configure it in the Character Mappings tab. If you uninstall a layout, its configuration will still be saved in the app's settings, but it will essentially be redundant – the layout is not present in the system anymore and hence the service app won't need its configuration. When you uninstall a layout and open the settings app, it will show you a warning and a button to delete the unused configuration. If you want to ignore this warning for whatever reason, then uncheck this checkbox.

The fifth checkbox controls whether the converter is visible. Since this is a very niche feature, you will likely never need to use it, so it's hidden by default.

## Switch Settings

You can switch text just by pressing modifier keys. This is similar to switching keyboard layouts in Windows itself – the default key combination to switch layouts in Windows is <kbd>Alt</kbd>+<kbd>Shift</kbd>. You can control which key combination to press to switch text and how many times. The setting contains four fields:

* Modifier keys for switching forward
* Modifier keys for switching backward
* Press count
* Wait time (in milliseconds)

You can select <kbd>Ctrl</kbd>, <kbd>Alt</kbd>, <kbd>Shift</kbd>*,* and <kbd>Win</kbd> (also known as <kbd>Super</kbd>, <kbd>Meta</kbd>, or <kbd>Command</kbd>), or their combination as modifier keys for switching. The default is <kbd>Ctrl</kbd>+<kbd>Shift</kbd> to switch forward, and <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> to switch backward.

You can also control how many times you should press those modifier keys to switch the text. The default is 2. Max value for this field is 10, but even that is way too much. Min value is 1, but be careful if you set it to 1, because then it would be easy to press it by accident.

Wait time controls how much time the service app waits before deciding that you're not intending on switching text. For example, let's say that the press count is 3, and wait time is 400 ms (which is the default value). You press the key combination. The app then waits for 400 ms to see whether you will press the key combination again. If you don't, then it realizes that you don't want to switch text. If you press the key combination again within this time, the app will then wait again for 400 ms. You then press the key combination for the third time, and the app realizes that you want to switch the text. The min value for this field is 100 ms (which usually makes the app give up waiting much too fast), and the max value for this field is 1000 ms (so, 1 full second, which is usually too slow). 400 ms is the sweet spot, but maybe it won't be for you. You should play around with this setting to figure out which value works best for you.

{% hint style="info" %}
Wait time is ignored if the press count is set to 1.
{% endhint %}

## Layout Settings (Linux Only)

These settings are present only on Linux, because unlike Windows, the app doesn't know how to switch layouts directly there. Instead, it will simulate pressing a key combination to switch the layout forward or backward.

{% hint style="warning" %}
These settings should rarely be changed since the defaults will almost certainly work.
{% endhint %}

The settings include the key combinations to switch forward or backward, and buttons to clear these key combinations. The defaults are <kbd>Left Super</kbd>+<kbd>Space</kbd> to switch forward, and <kbd>Left Shift</kbd>+<kbd>Left Super</kbd>+<kbd>Space</kbd> to switch backward. The <kbd>Super</kbd> key is also known as the <kbd>Windows</kbd> key (or simply <kbd>Win</kbd>) since it's the one with the Windows logo on most keyboards. If you do want to change them, clear the key combination, click on the text field, and press the key combination of your choice. The app will then use this key combination to switch layouts.

Since GNOME doesn't let the app react to pressing the <kbd>Super</kbd> keys, those keys can be added manually using the *Add Left Super* or *Add Right Super* buttons.


# Converter

The converter lets you manually convert text between arbitrary layouts, not just those installed in your system. In order to enable it, check the *Show the converter* checkbox in the Preferences tab.

{% hint style="info" %}
Converter is a very niche feature. Chances are that you'll never need to use it and never even think of using it, and that's why it's hidden by default. Moreover, it has nothing to do with the main functionality of the app – switching text in the background. Feel free to skip this article if you're not interested.
{% endhint %}

## The Converter Functionality

Here's how the Converter tab looks (when it's configured):

![The converter tab](https://2323494160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQRd6i8Vkkjc7Ss7rkN-1834917677%2Fuploads%2F7UtJNdQ63pvhFsnTn3rZ%2Fv4.0-screen-converter.png?alt=media\&token=be760b24-00b2-491b-8976-12cb1d133879)

The tab consists of two main parts:

* Text area
* Configuration area

Text area is where you input text and get the output. Quite straightforward.

Configuration area is where you configure how to switch the text. You can select the source layout and the target layout, and do the actual switching or clearing of the output.

Custom layouts are configured in the Converter Settings tab, discussed in the next section.

{% hint style="info" %}
At least two custom layouts are required to enable the converter.
{% endhint %}

## Converter Settings

The Converter Settings tab lets you configure custom layouts for the converter. Here's how it looks:

![The converter settings tab](https://2323494160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQRd6i8Vkkjc7Ss7rkN-1834917677%2Fuploads%2Fa13AZtoeuGC7YiPPGcrs%2Fv4.0-screen-converter-settings-main.png?alt=media\&token=d2abd0fd-86fe-419b-974d-774fd2fef114)

It's pretty similar to the Character Mappings tab, and the way configuration of characters works is identical. The main difference is that you can control what's shown here. You can add layouts, remove, or rename them. You can't change the order of the layouts, but it doesn't actually matter here. You can't have two or more layouts with the same name.

Just like with Character Mappings, you can auto-configure custom layouts, but here you have to select layouts to configure first. This is available only on Windows though. Here's how the settings for auto-configuration look:

![The settings for converter auto-configuration](https://2323494160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQRd6i8Vkkjc7Ss7rkN-1834917677%2Fuploads%2Ft3m5Aee1JZZcEgmGop1w%2Fv4.0-screen-converter-settings-config.png?alt=media\&token=e1bb42fe-7366-4c66-bc31-8d5e4f307e9a)

You can select layouts using the drop-down. It includes all keyboard layouts that you can choose in Windows. After you selected the layouts, and clicked *Save*, the app will load those layouts into Windows, execute the same auto-configuration algorithm as it does in the Character Mappings tab, and then unload those layouts from the system.

{% hint style="info" %}
It's best to auto-configure all layouts you want to add at once. If you auto-configure them one by one, then some characters may not be mapped correctly since auto-configuration will remove mappings which are not defined in *all* layouts.
{% endhint %}

## Why the Converter Was Added

Now that you know what the converter does, you'll agree that its use is extremely limited. And to be honest, the reason I've added it is not usability, it's sentimentality. A very long time ago, when the idea that there should be a way to easily switch mistyped text first occurred to me, I created an app (simply called Converter) which did just that, but it didn't do it in the background. You had to enter text in a window much the same way you have to do it in the converter in this app. It was actually one of the first usable apps that I have ever created. And this app even helped me out once, when I had to use a computer abroad and it didn't have the Ukrainian layout installed. So, after releasing version 2 of this app in 2018 I thought that it would be nice to add the converter feature to the next release even though it will probably not be used by anybody (not even me). In addition, I've learned a couple interesting things about how keyboard layouts work in Windows when I implemented this feature. So here we are.


# Other Tabs

Other tabs in the settings app include the Sandbox tab and the About tab.

## Sandbox

Sandbox is absurdly simple – it's just a text box. That's it! Here's how it looks:

![The sandbox tab](https://2323494160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQRd6i8Vkkjc7Ss7rkN-1834917677%2Fuploads%2FuiMXvNw5K76eX5fwiNOG%2Fv4.0-screen-sandbox.png?alt=media\&token=9a4e2cdd-4dc8-4259-98e5-5afe00f7dc6d)

Sandbox lets you play around with switching text when you change the app's settings. It contains no logic whatsoever. It's literally just a text box.

## About

The About tab contains some general info about the app. Here's how it looks:

![The about tab](https://2323494160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQRd6i8Vkkjc7Ss7rkN-1834917677%2Fuploads%2FqJ67MoyyCj9PsxahNGHZ%2Fv4.0-screen-about.png?alt=media\&token=0c486905-bddb-46fb-9559-26cc4b21b515)

If you want more info, you can view the docs (these very pages).

You can also check whether updates for the app are available. If they are indeed available, then you can go to the releases page on GitHub to get them. The app doesn't support auto-updating, so you will have to install a newer version yourself (if you installed the current version). Remember that you have to stop the service app before installing a newer version.

That's it for the settings app. If you want technical info about Keyboard Switch, you can check out the next articles.


# Command Line Interface

The Keyboard Switch service app has a CLI which you can use to control it. On Windows, it's not really convenient as GUI apps cannot output anything to the console, but it can be used as well.

The name of the executable is `KeyboardSwitch`. This article will assume it's installed on Linux in the `/opt/keyboard-switch` directory.

## Commands

### Running the App

To start KeyboardSwitch, simply run it in the terminal:

```
/opt/keyboard-switch/KeyboardSwitch &
```

The `&` makes the service app run in the background. On Windows, the `&` is not needed as GUI apps always run separately from the terminal.

Keyboard Switch is a single-instance app. If one instance is already running, and you start another one, it will immediately silently exit.

### Stopping the App

To stop Keyboard Switch, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --stop
```

If an instance of Keyboard Switch is running, this command will stop it. If no instance is running, it will do nothing.

### Reloading the Settings

To reload the settings of Keyboard Switch, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --reload-settings
```

If an instance of Keyboard Switch is running, this command will make it invalidate its current settings and reload them. If no instance is running, it will do nothing.

### Checking Whether the App Is Running

To check whether KeyboardSwitch is running, run the following:

```
/opt/keyboard-switch/KeyboardSwitch --check
```

If an instance of Keyboard Switch is running, this command will output `KeyboardSwitch is running`. Otherwise, it will output `KeyboardSwitch is not running`.

### Showing a Help Message

To show the help message, run either of the following:

```
/opt/keyboard-switch/KeyboardSwitch --help
/opt/keyboard-switch/KeyboardSwitch -?
```

### Command Formats

The aforementioned commands can be prefixed with `--`, `-`, or `/`. For example, to stop Keyboard Switch, you can specify `stop`, `-stop`, `--stop`, or `/stop`.

## Exit Codes

The following exit codes are available:

* `0` – The app has exited successfully.
* `1` – An unspecified error has occurred.
* `2` – The app cannot run, because its settings have an incompatible version. The app is backward-compatible with respect to settings versions – it will read the settings created by an older version and modify them to fit the current version. But it's not forward-compatible – version 4.0 will not work if the settings were created or updated by a newer version.
* `3` – `stop`, `reload-settings`, or `check` was specified as the command, but no instance of Keyboard Switch is running.
* `4` – An invalid command was specified.


# Technical Stuff

Keyboard Switch is written using [C#](https://github.com/dotnet/csharplang) and [.NET 6](https://dotnet.microsoft.com/download/dotnet/6.0). Following is the list of technologies used in this app and some other technical aspects.

## UI

The Keyboard Switch Settings app is written using [Avalonia](https://avaloniaui.net), a cross-platform UI framework for .NET. I chose it because unlike other UI frameworks for .NET, it's cross-platform, and I had to do literally nothing for it to work on Linux as well. The style is provided by [FluentAvalonia](https://github.com/amwx/FluentAvalonia).

Previous versions of the app used .NET Framework and WPF. Back then I didn't expect to have it working on different platforms.

Previous versions of the app also included a tray icon so you could see that the app is running. I removed it in version 3.0 as I don't see much value in keeping it and cluttering your tray.

## Core Logic

### Windows

The service app is just an app which runs in the background. I could have made it into a Windows service but decided against it when I read somewhere that Windows services cannot set up keyboard hooks. I didn't actually verify this info, so I'm not sure it's correct, but the background app approach works just fine, so it's likely to stay this way.

The service app calls various native functions from the Windows' *user32.dll*. It uses [Vanara](https://github.com/dahall/Vanara) to call them.

In the previous versions (up to 3.0) the service and the settings app were not separated. It was just an app running with a hidden window which showed up when you opened it. Having a hidden window always loaded is not that great of an idea, even though it used very little RAM.

### Linux

At first, I decided to run the app as a *systemd* service, but it proved not to provide much value, so I've since reverted this decision.

The service app uses X11, especially the X Keyboard Extension, and the X Test Extension. Currently it doesn't work on Wayland, even through XWayland. It uses the [X11](https://www.nuget.org/packages/X11/) package to call various native Xlib functions.

The app also uses Bash and [xsel](https://github.com/kfish/xsel), but those are not used directly – rather they are used by the [TextCopy library](https://github.com/CopyText/TextCopy) which the app uses for copying and pasting text.

### The Settings App

The core logic of the settings app is implemented using [ReactiveUI](https://www.reactiveui.net) as the MVVM framework. Also, [Splat](https://github.com/reactiveui/splat) is used for service location.

## The Global Keyboard Hook

The app uses [libuiohook](https://github.com/kwhat/libuiohook) to create a global keyboard hook. The library is cross-platform and supports almost all popular OSes and architectures. Since this library is native and it's non-trivial to build, I've developed a .NET wrapper for it, [SharpHook](https://github.com/TolikPylypchuk/SharpHook), so that I don't have to deal with a native library in this project.

Previously, the app used a Windows keyboard hook directly, but that doesn't work on other systems.

## Preferences

Preferences are stored in the user's local app data folder (under the *KeyboardSwitch* directory) on Windows. I didn't put it into the normal app data folder because that one is shared if you use the same Windows account on multiple machines, and that kind of defeats the purpose of this app being configured for each machine individually.

On Linux the settings are stored in the *\~/.keyboard-switch* directory.

This app uses [Akavache](https://github.com/reactiveui/Akavache) as the engine for storing settings.

## Logging

This app uses a plain-text log file to log the stuff it’s doing and errors it encounters along the way. [Serilog](https://serilog.net) is used as the logging library. The log file is stored in the same folder as the preferences and is rolled over after reaching 10 MB. If you really want to (and know how), you can change the logging configuration in the *appsettings.json* file (which is located in the same folder as the app itself).

## Tests

There are none. Honestly, I don't even know how to approach testing, because the core logic of the app is essentially creating system-wide side effects, so don't think it's really testable. As for the settings app, well, I could test it, but that would take a lot of time, and the app is pretty simple, so I don't plan on doing it in the nearest future.

## Docs

The docs are built and hosted on [GitBook](https://www.gitbook.com).

Previously these articles were built using [Jekyll](https://jekyllrb.com) and hosted on [GitHub Pages](https://pages.github.com), and used the [Minimal Mistakes theme](https://mmistakes.github.io/minimal-mistakes).

## Building from Source

You can build Keyboard Switch from source if you like. All projects (except the Windows installer) require .NET 6.

### The Projects

The app consists of 7 projects:

* *KeyboardSwitch*: The Keyboard Switch service itself
* *KeyboardSwitch.Core*: Core functionality and interfaces for the projects
* *KeyboardSwitch.Settings*: The Keyboard Switch Settings app
* *KeyboardSwitch.Settings.Core*: The core logic of the settings app
* *KeyboardSwitch.Windows*: The implementation of the core functionality for the Windows platform
* *KeyboardSwitch.Linux*: The implementation of the core functionality for the Linux platform
* *KeyboardSwitch.Windows.Setup*: The setup project

### Building the App Itself

Building the service app and the settings app is quite straightforward.

On Windows, you can simply use the *Build-Portable.ps1* script located in the *build/windows* directory. Bear in mind that you have to call this script from the solution root directory: `.\build\windows\Build-Portable.ps1`. It will create the *KeyboardSwitch-Portable.zip* file in the *bin* directory which you can then unpack into wherever you like.

On Linux, you should use the *build-tar.sh* script to build the tar.gz file, the *build-deb.sh* script to build the deb package, and the *build-rpm.sh* script to build the RPM package. They are located in the *build/tar*, *build/deb*, and *build/rpm* directories respectively. As with the Windows script, you have to execute these scripts from the solution root: `./build/tar/build-tar.sh`, `./build/deb/build-deb.sh`, and `./build/rpm/build-rpm.sh`. The scripts' results will be in the *bin* directory.

Alternatively, you can build the projects using Visual Studio 2019 or later, or with the `dotnet` tool. Note however that you have to build the whole solution. The startup project is *KeyboardSwitch.Settings*, and if you build it, it won't actually build the *KeyboardSwitch* project, because the settings app doesn't directly depend on the service app.

All projects (except the installer) are built into a shared *bin* folder located in the solution root. Again, this is because the settings app needs the service app to be in the same folder, but the projects don't depend on each other.

It's better to use `dotnet publish` than simply using the raw build results. You can look into how the build scripts call `dotnet publish`.

The installer project is excluded from the solution build sequence as it's not always needed.

### Building the Windows Installer

If you want to properly install the app on Windows, you can build the installer. Unlike the other projects, this one requires .NET Framework 4.8. This is because it's built with [WixSharp](https://github.com/oleg-shilo/wixsharp), which in turn is based on [the WiX toolset](https://wixtoolset.org), and as of version 3.11.2, WiX doesn't support .NET 6.

Simply run the build, and it will generate the MSI installer in the project's *bin* folder. Before the build, it calls `dotnet publish` to use its output.


# About

Keyboard Switch. Version 4.0. Created by [Tolik Pylypchuk](https://github.com/TolikPylypchuk).

## Acknowledgements

The UI for the settings app was created using [Avalonia](https://avaloniaui.net/) with [ReactiveUI](https://www.reactiveui.net/) and [FluentAvalonia](https://github.com/amwx/FluentAvalonia). The global keyboard hook is implemented using [libuiohook](https://github.com/kwhat/libuiohook). Docs are built using [GitBook](https://www.gitbook.com). Icon made by [Smashicons](https://smashicons.com/) from [www.flaticon.com](https://www.flaticon.com/).

## Changelog

### [v4.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v4.0) (28 November 2021)

* The app now works on Linux (via X11 only; Wayland is not supported)
* The legacy hot-key mode was removed – only the modifier keys mode is available
* The UI theme is overhauled
* The converter is hidden by default
* .NET 6 is used instead of .NET Core 3.1
* The app's performance was improved, though it's still not ideal

This is the first major version of the app which is not completely rewritten, though it was significantly changed. From now on, most changes (like macOS support) will come as minor versions, and version 4 will be the major version for the foreseeable future.

### [v3.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v3.0) (4 August 2020)

* A completely rewritten app based on .NET Core and working as a truly UI-less app instead of an app with a hidden window
* The settings are now a separate app written with Avalonia instead of WPF
* Tray icon was removed
* Added the ability to switch between multiple layouts of the same language (e.g. QWERTY and Dvorak for English)
* Instant switching mode is not experimental anymore and enabled by default
* Added the ability to auto-configure character mappings
* Added checking for updates

### [v2.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v2.1) (1 April 2018)

Minor bug fixes

### [v2.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v2.0) (13 January 2018)

* Brand new installer for the app
* Instant switching mode
* Updated readme
* Updated configuration
* Minor UI updates
* Minor bug fixes

### [v1.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v1.1) (somewhere in 2015)

Minor bug fixes

### v1.0 (somewhere in 2015)

All the basic functionality:

* Switching text
* Starting at system startup
* Tray icon

## License

MIT License

Copyright (c) 2015 Anatoliy Pylypchuk

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


# Keyboard Switch

Welcome to the Keyboard Switch docs!

Keyboard Switch is an application which switches typed text as if it were typed with another keyboard layout.

If you ever write some text and then realize that you have written it using a wrong layout, you don't have to delete it and start over anymore. Just select the text, press a magic key combination, and that's it!

I hope this app will make your life at least 1% easier :)

{% hint style="info" %}
If you're using version 3, then you should upgrade to version 4 as soon as possible since it contains major improvements.
{% endhint %}

## How The App Works

The app is composed of two parts: the Keyboard Switch service and the Keyboard Switch Settings app. The service always runs in the background (and starts when you log into the system) and listens to key presses. When you press the magic key combination, it reacts by copying the selected text, transforming it, and pasting it for you. The settings app is used for configuring the service and for starting/stopping it manually.

Here are the basic steps you should take to switch the text:

* Type some text using an incorrect layout
* Realize your mistake
* Select the text (you can press <kbd>Ctrl</kbd>+<kbd>A</kbd> to select all text)
* Press the magic key combination (the default is pressing <kbd>Ctrl</kbd>+<kbd>Shift</kbd> twice)
* Profit

The app uses the clipboard to get the text to transform and then puts the transformed text back into the clipboard. Bear this in mind when you use it – if you have anything else in the clipboard, it will be lost. This isn't that big of an issue since Windows 10 October 2019 Update, because you can enable multiple items in the clipboard.

{% hint style="info" %}
The app simulates pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> to copy and <kbd>Ctrl</kbd>+<kbd>V</kbd> to paste text. This is the default behavior for most (if not all) applications. But if you are working in an app which behaves differently on those key presses, this app will not be able to instantly switch text. You can disable this behavior and copy/paste the text manually.
{% endhint %}

## Supported Platforms

This app works only on Windows 10 and 11. It can probably work on older versions of Windows as well, but I'm not going to support them. Future versions of the app will be supported on other platforms, so if you don't use Windows then stay tuned!

## Layouts

The app uses the list of your layouts in the same order as defined by the system. You can switch both forward and backward through this list. The app also automatically changes your layouts, so you don't have to do it yourself. You can disable this as well if you so wish. You cannot add a layout that's not present as one of the system's layouts. If you add/remove a layout while the app is running, you'll have to configure it in the settings and restart the service.

{% hint style="info" %}
This app is "Western-oriented". I developed it specifically to handle switching between Cyrillic and Latin scripts. I don't know how it will work (if at all) with Eastern languages/scripts.
{% endhint %}


# Installation

## Using a Windows Installer

You can get the latest version of the app from the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases). Download the *.msi* file and run it to install the app.

After installing the app, the installer will run the settings app. Currently it's not really optimized, so the startup time is not perfect; it can take a couple seconds for the app to get started. On the first start up, the settings app will configure the service to run when you log into the system.

If multiple users use the PC, then bear in mind that the app configures itself to run on log-in only for the user that installed the app. Other users have to configure it manually.

When the settings app starts up, you should configure the character mappings (you can read more about it in the next article). After you have configured the character mappings and possibly some other preferences, start the app using the *Start* button at the bottom of the window. That's it! Now you're ready to use the Keyboard Switch service.

## Uninstalling the App

You can uninstall the app using the Settings app just like you would uninstall any other app.

{% hint style="warning" %}
The installer will not delete the registry entry which says that your app should start when you log in. If you want to keep your registry clean, you have to disable it in the settings app before uninstalling it.
{% endhint %}

Upon uninstallation the installer will ask whether you want to delete the app's configuration as well. If you choose not to delete the configuration, you can delete it later manually at any other time. It's stored under the user's local app data folder.

{% hint style="warning" %}
The installer will only delete the current user's configuration. If there are other users on the PC, they will have to delete the configuration manually.
{% endhint %}

## Using the Portable Version

If you don't want to install the app (or can't), you can use the portable version of the app. It's literally the same as the installable version; there are no differences. Again, go to the [releases page on GitHub](https://github.com/TolikPylypchuk/KeyboardSwitch/releases) and download *KeyboardSwitch-Portable.zip*. Extract the archive to anywhere you want and start *KeyboardSwitchSettings.exe*. You can configure the app to run when you log in just like the installed version. The configuration for the portable version is also stored under the user's local app data folder.


# The Settings App

Keyboard Switch Settings is a simple app which controls the behavior of the Keyboard Switch service. If you installed the app using a Windows installer, you can find the app in the Start menu. Here's how it looks:

![](https://642764896-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQRd6i8Vkkjc7Ss7rkN%2F-MQRfOheh3j_VsIm-FHx%2F-MQRikAjJ2e71ZfRmxSw%2Fv3.0-screen-char-mappings.png?alt=media\&token=46cb179e-ce8e-4808-a9cc-1bb33f4abc8f)

The app is composed of six tabs:

* Character mappings: contains the settings which tell Keyboard Switch how to transform characters between layouts
* Preferences: contains other settings
* Converter: lets you manually convert text between arbitrary custom layouts
* Converter settings: contains the list of custom layouts for the converter
* Sandbox: lets you play around with switching the text
* About: contains info about the app

At the bottom there's a strip with the status of the Keyboard Switch service. If it's not running, you can press the *Start* button to start it manually (although usually you wouldn't do that because the service will start when you log in). If the service is running, you can stop it by pressing the *Stop* button. It won't actually kill it — it will send a *stop* command, and the service will do some clean-up and stop on its own. If it's taking a long time to stop, it may mean that something went wrong. In that case you can force it to stop by pressing the *Kill* button.

{% hint style="info" %}
If you change anything in the settings app, you can save it or cancel it. When you save it, the settings app sends a notification to the service app (if it's running) about changes in configuration, so you don't have to restart the service after saving.
{% endhint %}

The following articles describe each tab of the settings app in more detail.


# Character Mappings

In order for the Keyboard Switch service to know how to map characters, you have to configure the character mappings yourself. The app reads the list of installed layouts in the system, so it knows which layouts you use and in what order. What it doesn't (and can't) know is the physical layout of your keyboard, so it doesn't know what happens if you press certain keys on your keyboard.

## Text vs Keyboard

This section explains *why* you need to configure character mappings for the app. If you're not interested, feel free to skip it.

Working with text and working with keyboard are two wildly different things. You, the user of a computer, usually work with a keyboard (or other input devices, but those don't matter here). This app however works with text (even though its name might suggest differently), and so text transformation during switching will most probably not be perfect.

Ideally you wouldn't have to configure the app at all – it would just know how to transform the text you mistyped into another layout. After all, the OS somehow knows which characters to produce when you press various keys. But going that way would be extremely difficult, if not impossible.

Firstly, pressing keys and entering characters are absolutely not the same thing. Many keys don't have corresponding characters at all, like <kbd>Ctrl</kbd> or <kbd>Page Up</kbd>. The same key press can produce different characters based on the state of other keys. For example, the <kbd>A</kbd> key usually produces **a**, but when <kbd>Shift</kbd> is down, the key produces **A**. And then there are dead keys – key combinations that produce one character by pressing two (or even three) keys. For example, in the US International layout, pressing <kbd>'</kbd> and then <kbd>A</kbd> will produce **á**.

Secondly, it's impossible to know which keys have been pressed just by looking at text. This is because the same character can be produced using different keys or key combinations (or it can be pasted, so the keyboard wouldn't be used at all).

So, in order to just know how to transform the text you've mistyped, the app would have to keep track of the keys you've pressed and then infer which of those pressed keys actually played a role in producing the mistyped text and then ask the OS which characters would be produced with the same key sequence. You can see how that's unreasonable. First of all, the app would have to track *all* the keys you press, and that would be quite sketchy. Would you trust an app which logs everything you type? I certainly wouldn't. And ethics aside, there still are technical issues. How many keys should the app track? What happens if the user pastes part of the text instead of typing it? Etc., etc.

And that's why the app uses a much simpler solution – it lets you, the user, figure out how the text should be transformed. The app can auto-configure the mappings using a simple method, but it's still up to you to check whether it's all correct.

## How Character Mappings Work

Here's how the tab looks when the app is opened for the first time:

![The character mappings tab when the configuration is empty](https://642764896-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQRd6i8Vkkjc7Ss7rkN%2F-MQRfOheh3j_VsIm-FHx%2F-MQRikAkWBov48mNUmN8%2Fv3.0-screen-char-mappings-empty.png?alt=media\&token=679595ed-4c8f-49ed-b3be-d087cddeb3d0)

You have to enter every character you can think of (which can be entered using your keyboard) into the text fields which correspond to layouts. For example, press the <kbd>Q</kbd> key, then press the <kbd>W</kbd> key, and so on. Then press <kbd>Shift</kbd>+<kbd>Q</kbd>, then <kbd>Shift</kbd>+<kbd>W</kbd> etc. to add uppercase letters.

You should press the keys *in the same order* for all layouts. Order matters here because the service will look at characters in same positions to determine how to transform the text. For example, let's say you have two layouts in your system: English (US) and Ukrainian (Enhanced). You put **q** as the first character in the text field for English, and **й** as the first character in the text field for Ukrainian (because that's the character you get when you press the <kbd>Q</kbd> key). Now the service will know that when it switches from English to Ukrainian, it should transform **q** to **й**. If the second characters are **w** and **ц** for English and Ukrainian respectively, then the service will transform **w** to **ц**.

If you don't want to map a certain character, you can put a space in its position in the other layout. The space character acts as a *don't map this character* command, though it should generally be avoided.

## Auto-Configuration

Even though you have to do it only once, configuring character mappings is still cumbersome and error-prone. That's why the app includes the auto-configuration feature. It's available only when all text fields are empty. The auto-configuration is quite simple (naïve even), and it shouldn't be 100% trusted, so you still have to check its output and fix mistakes or add other characters manually. But usually auto-configuration should be good enough.

Here's how the tab looks after running auto-configuration:

![The character mappings tab after auto-configuration](https://642764896-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQRd6i8Vkkjc7Ss7rkN%2F-MQRfOheh3j_VsIm-FHx%2F-MQRikAiK-jL8CZ33mvy%2Fv3.0-screen-auto-configuration.png?alt=media\&token=984a3fdc-1796-40f1-a78f-830b0c298748)

What auto-configuration does is basically ask the OS what would happen if certain keys were pressed using various layouts. There is no easy way to get the information about *all* keys on your keyboard, so it asks only about the most common ones. Here's the list of those keys for the US layout:

* All letter keys (<kbd>Q</kbd>, <kbd>W</kbd>, <kbd>E</kbd> etc.)
* Number keys
* Other common keys: <kbd>\[</kbd>, <kbd>]</kbd>, <kbd>;</kbd>, <kbd>'</kbd>, <kbd>,</kbd>, <kbd>.</kbd>, <kbd>/</kbd>, <kbd>\\</kbd>, <kbd>-</kbd>, <kbd>=</kbd>, and <kbd>\`</kbd>
* All those keys with the <kbd>Shift</kbd> key
* All those keys with the <kbd>AltGr</kbd> key
* All those keys with the <kbd>Shift</kbd>+<kbd>AltGr</kbd> keys

Not all of those key combinations actually produce characters for all layouts. So, after asking the OS about all of these keys, the app keeps only those character combinations which are defined for all layouts. For example, if you press <kbd>AltGr</kbd>+<kbd>U</kbd> in the Ukrainian layout, you will get **ґ**, but if you press those keys in the US layout, you won't get anything at all, so the app will just throw **ґ** out as it won't know how to map it to the US layout.

## Limitations

You can map every character only once per layout. Otherwise, it would be impossible to map characters deterministically.

Characters are always mapped one to one. You cannot map one character to several characters.

Dead keys are not supported.

The space character cannot be mapped to other characters. This is not really a limitation, because the space character is the same in every layout (at least that's the assumption).

The app doesn't play nicely with text if you switched the layout yourself in the middle of typing. If that's the case, the app will not switch it correctly, and you will have to fix some of it yourself.


# Preferences

The Preferences tab contains other settings which control the behavior of the Keyboard Switch service. It has two main looks, based on the switch mode setting:

![The preferences tab with the Modifier keys switch mode](https://642764896-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQRd6i8Vkkjc7Ss7rkN%2F-MQRfOheh3j_VsIm-FHx%2F-MQRikAoD231Yi2PDd6M%2Fv3.0-screen-preferences-1.png?alt=media\&token=bca8a786-2575-46f8-8ab6-c390fb7b5d0c)

![The preferences tab with the Hot key switch mode](https://642764896-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQRd6i8Vkkjc7Ss7rkN%2F-MQRfOheh3j_VsIm-FHx%2F-MQRikApZILlw4oH8PWX%2Fv3.0-screen-preferences-2.png?alt=media\&token=a8e4703b-79ef-49cb-9e9e-d4ea075569be)

Following is the discussion on the many fields that are in this tab.

## Checkboxes

There are four checkboxes at the top of the Preferences tab:

* Instant switching
* Switch layouts
* Start the service when you log in
* Show a message about uninstalled layouts

The first checkbox controls whether the Keyboard Switch service should use instant switching or not. The default is yes. The service app needs to access the text to transform it, and for that it uses the clipboard. When instant switching is enabled, the service app will simulate pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> to copy text into the clipboard. This is why you must first select the text before you let the service app switch it. After transforming the text, the service app will put it back into the clipboard and if the instant switching mode is enabled, it will simulate pressing <kbd>Ctrl</kbd>+<kbd>V</kbd> to paste the new text instead of the selected text. If you disable this mode, you will have to manually copy the text before switching and then paste it afterwards.

The second checkbox controls whether the service app should switch the layout for you after transforming the text. The default is yes, and to be honest, I see no reason to ever disable it. It just reduces the number of actions you have to do in order to get back on track with typing the text.

The third checkbox lets you control whether the service app will start when you log in. The default is yes if you installed the app using a Windows installer, and no if you're using the portable version.

The fourth checkbox controls whether the settings app should show a warning about uninstalled layouts. If you install a new layout in the system, you should open the settings app and configure it in the Character Mappings tab. If you uninstall a layout, its configuration will still be saved in the app's settings, but it will essentially be redundant – the layout is not present in the system anymore and hence the service app won't need its configuration. When you uninstall a layout and open the settings app, it will show you a warning and a button to delete the unused configuration. If you want to ignore this warning for whatever reason, then uncheck this checkbox.

## Switch Mode

The service app supports two switching modes in relation to the magic key combinations you press to switch the text: modifier keys (the default), and hot key.

### Modifier Keys

This is the default and recommended switch mode. With it you can switch text just by pressing modifier keys. This is similar to switching keyboard layouts in Windows itself – the default key combination to switch layouts in Windows is <kbd>Alt</kbd>+<kbd>Shift</kbd>. You can control which key combination to press to switch text and how many times. The setting contains four fields:

* Modifier keys for switching forward
* Modifier keys for switching backward
* Press count
* Wait time (in milliseconds)

You can select <kbd>Ctrl</kbd>, <kbd>Alt</kbd>, <kbd>Shift</kbd> or their combination as modifier keys for switching. The default is <kbd>Ctrl</kbd>+<kbd>Shift</kbd> to switch forward, and <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd> to switch backward. The app doesn't distinguish between left and right modifier keys.

You can also control how many times you should press those modifier keys to switch the text. The default is 2. Max value for this field is 10, but even that is way too much. Min value is 1, but be careful if you set it to 1, because then it would be easy to press it by accident.

Wait time controls how much time the service app waits before deciding that you're not intending on switching text. For example, let's say that the press count is 3, and wait time is 300 ms (which is the default value). You press the key combination. The app then waits for 300 ms to see whether you will press the key combination again. If you don't, then it realizes that you don't want to switch text. If you press the key combination again within this time, the app will then wait again for 300 ms. You then press the key combination for the third time, and the app realizes that you want to switch the text. The min value for this field is 100 ms (which in my opinion makes the app give up waiting much too fast), and the max value for this field is 1000 ms (so, 1 full second, which as for me is too slow). 300 ms is the sweet spot for me, but maybe it won't be for you. You should play around with this setting to figure out which value works best for you.

{% hint style="info" %}
Wait time is ignored if the press count is set to 1.
{% endhint %}

### Hot Key

The hot key switch mode was carried over from the previous version of the app and is not recommended anymore. It lets you specify which key combination (modifier keys + normal key) to press to switch the text. There are three fields for this mode:

* Modifier keys
* Forward key
* Backward key

The default modifier keys are <kbd>Ctrl</kbd>+<kbd>Shift</kbd>, and the default keys are <kbd>X</kbd> for forward and <kbd>Z</kbd> for backward. So, to switch forward, you just press <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>X</kbd> and that's it. The fields for keys only allow a limited set of keys (arrow keys or navigation keys are not allowed for example).

This mode is not recommended anymore because it may interfere with the app you're using at the moment – the app itself may do something when you press, say, <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>X</kbd>. There's no way of knowing that the key combination you selected is never used in any app ever.

{% hint style="info" %}
You can't change the switch mode if there are unsaved changes in the Preferences tab. Save or cancel the changes if you want to change it.
{% endhint %}


# Converter

Converter lets you manually convert text between arbitrary layouts, not just those installed in your system.

{% hint style="info" %}
Converter is a very niche feature. Chances are that you'll never need to use it and never even think of using it. Moreover, it has nothing to do with the main functionality of the app – switching text in the background. Feel free to skip this article if you're not interested.
{% endhint %}

## The Converter Functionality

Here's how the Converter tab looks (when it's configured):

![The converter tab](https://642764896-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQRd6i8Vkkjc7Ss7rkN%2F-MQRfOheh3j_VsIm-FHx%2F-MQRikAlc1VyR5KNnSel%2Fv3.0-screen-converter.png?alt=media\&token=132fc3d1-6762-4679-8950-90d6af54e244)

The tab consists of two main parts:

* Text area
* Configuration area

Text area is where you input text and get the output. Quite straightforward.

Configuration area is where you configure how to switch the text. You can select the source layout and the target layout and do the actual switching or clearing of the output.

Custom layouts are configured in the Converter Settings tab, discussed in the next section.

{% hint style="info" %}
At least two custom layouts are required to enable the converter.
{% endhint %}

## Converter Settings

The Converter Settings tab lets you configure custom layouts for the converter. Here's how it looks:

![The converter settings tab](https://642764896-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQRd6i8Vkkjc7Ss7rkN%2F-MQRfOheh3j_VsIm-FHx%2F-MQRikAnGBEZxN6io3wU%2Fv3.0-screen-converter-settings-main.png?alt=media\&token=830d9806-cabd-41c6-a872-6fc7fa48b97d)

It's pretty similar to the Character Mappings tab, and the way configuration of characters works is identical. The main difference is that you can control what's shown here. You can add layouts, remove, or rename them. You can't change the order of the layouts, but it doesn't actually matter here. You can't have two or more layouts with the same name.

Just like with Character Mappings, you can auto-configure custom layouts, but here you have to select layouts to configure first. Here's how the settings for auto-configuration look:

![The settings for converter auto-configuration](https://642764896-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQRd6i8Vkkjc7Ss7rkN%2F-MQRfOheh3j_VsIm-FHx%2F-MQRikAmpegVFNtppiKy%2Fv3.0-screen-converter-settings-config.png?alt=media\&token=02b18b64-355c-4f9d-a6c0-f0125c88674f)

You can select layouts using the drop-down. It includes all keyboard layouts that you can choose in Windows. After you selected the layouts, and clicked *Save*, the app will load those layouts into Windows, execute the same auto-configuration algorithm as it does in the Character Mappings tab, and then unload those layouts from the system.

{% hint style="info" %}
It's best to auto-configure all layouts you want to add at once. If you auto-configure them one by one, then some characters may not be mapped correctly since auto-configuration will remove mappings which are not defined in *all* layouts.
{% endhint %}

## Why the Converter Was Added

Now that you know what the converter does, you'll agree that its use is extremely limited. And to be honest, the reason I've added it is not usability, it's sentimentality. A very long time ago, when the idea that there should be a way to easily switch mistyped text first occurred to me, I created an app (simply called Converter) which did just that, but it didn't do it in the background. You had to enter text in the window much the same way you have to do it in the converter in this app. It was actually one of the first usable apps that I have ever created. And this app even helped me out once, when I had to use a computer abroad and it didn't have the Ukrainian layout installed. So, after releasing version 2 of this app in 2018 I thought that it would be nice to add the converter feature to the next release even though it will probably not be used by anybody (not even me). In addition, I've learned a couple interesting things about how keyboard layouts work in Windows when I implemented this feature. So here we are.


# Other Tabs

Other tabs in the settings app include the Sandbox tab and the About tab.

## Sandbox

Sandbox is absurdly simple – it's just a text box. That's it! Here's how it looks:

![The sandbox tab](https://642764896-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQRd6i8Vkkjc7Ss7rkN%2F-MQRfOheh3j_VsIm-FHx%2F-MQRikAqyYJLhVSx9POZ%2Fv3.0-screen-sandbox.png?alt=media\&token=e52c852f-a609-429a-86ab-3aec91c9cb59)

Sandbox lets you play around with switching text when you change the app's settings. It contains no logic whatsoever. It's literally just a text box.

## About

The About tab contains some general info about the app. Here's how it looks:

![The about tab](https://642764896-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQRd6i8Vkkjc7Ss7rkN%2F-MQRfOheh3j_VsIm-FHx%2F-MQRikAeVwZ58m1hDaTJ%2Fv3.0-screen-about.png?alt=media\&token=2d308af8-834c-4ed9-b7cd-9208b1726b1c)

If you want more info, you can view the docs (these very pages).

You can also check whether updates for the app are available. If they are indeed available, then you can go to the releases page on GitHub to get them. The app doesn't support auto-updating, so you will have to install a newer version yourself (if you installed the current version). Remember that you have to stop the service app before installing a newer version.

That's it for the settings app. If you want technical info about Keyboard Switch, you can check out the next article.


# Technical Stuff

Keyboard Switch is written using [C#](https://github.com/dotnet/csharplang) and [.NET Core 3.1](https://github.com/dotnet/core). Following is the list of technologies used in this app and some other technical aspects.

## UI

The Keyboard Switch Settings app is written using [Avalonia](https://avaloniaui.net), a cross-platform UI framework for .NET. I chose it because unlike other UI frameworks for .NET, it's cross-platform, so when I implement the app for other platforms, I won't need to make major changes to the UI.

Previous versions of the app used .NET Framework and WPF. Back then I didn't expect to have it working on different platforms.

Previous versions of the app also included a tray icon so you could see that the app is running. I removed it in version 3.0 as I don't see much value in keeping it and cluttering your tray.

## Core Logic

The service app is just an app which runs in the background. I could have made it into a Windows service but decided against it when I read somewhere that Windows services cannot set up keyboard hooks. I didn't actually verify this info, so I'm not sure it's correct, but the background app approach works just fine, so it's likely to stay this way.

The service app calls various native methods from the Windows' `user32.dll`. It uses [Vanara](https://github.com/dahall/Vanara) to call them.

In the previous versions, the service and the settings app were not separated. It was just an app running with a hidden window which showed up when you opened it. Having a hidden window always loaded is not that great of an idea, even though it used very little RAM.

The core logic of the settings app is implemented using [ReactiveUI](https://www.reactiveui.net) as the MVVM framework. Also, [Splat](https://github.com/reactiveui/splat) is used for service location.

## Preferences

Preferences are stored in the user's local app data folder (under the *KeyboardSwitch* directory). I didn't put it into the normal app data folder because that one is shared if you use the same Windows account on multiple machines, and that kind of defeats the purpose of this app being configured for each machine individually.

This app uses [Akavache](https://github.com/reactiveui/Akavache) as the engine for storing settings.

## Logging

This app uses a plain-text log file to log the stuff it’s doing and errors it encounters along the way. [Serilog](https://serilog.net) is used as the logging library. The log file is stored in the same folder as the preferences and is rolled over after reaching 500 MB. If you really want to (and know how), you can change the logging configuration in the *appsettings.json* file which is located in the same folder as the app itself. But you're better off not touching that file at all.

## Tests

There are none. Honestly, I don't even know how to approach testing, because the core logic of the app is essentially creating system-wide side effects, so don't think it's really testable. As for the settings app, well, I could test it, but that would take a lot of time, and the app is pretty simple, so I don't plan on doing it in the nearest future.

## Docs

The docs are built and hosted on [GitBook](https://www.gitbook.com).

Previously these articles were built using [Jekyll](https://jekyllrb.com) and hosted on [GitHub Pages](https://pages.github.com), and used the [Minimal Mistakes theme](https://mmistakes.github.io/minimal-mistakes).

## Building from Source

You can build Keyboard Switch from source if you like. All projects (except the Windows installer) require .NET Core 3.1 or later.

### The Projects

The app consists of 6 projects:

* *KeyboardSwitch*: The Keyboard Switch service itself
* *KeyboardSwitch.Settings*: The Keyboard Switch Settings app
* *KeyboardSwitch.Settings.Core*: The core logic of the settings app
* *KeyboardSwitch.Common*: Common functionality and interfaces for the projects
* *KeyboardSwitch.Windows*: The implementation of common functionality for the Windows platform
* *KeyboardSwitch.Windows.Setup*: The setup project

### Building the App Itself

Building the service app and the settings app is quite straightforward. You can simply use the `Build-Portable` script located in the solution root. It will create the `KeyboardSwitch-Portable.zip` file in the `bin` folder which you can then unpack into wherever you like.

Alternatively, you can build the projects using Visual Studio 2019 or later, or with the `dotnet` tool. Note however that you have to build the whole solution. The startup project is *KeyboardSwitch.Settings*, and if you build it, it won't actually build the *KeyboardSwitch* project, because the settings app doesn't directly depend on the service app.

All projects (except the installer) are built into a shared *bin* folder located in the solution root. Again, this is because the settings app needs the service app to be in the same folder, but the projects don't depend on each other.

It's better to use `dotnet publish` than simply using the raw build results. You can look into how the `Build-Portable` script calls `dotnet publish`.

The installer project is excluded from the solution build sequence as it's not always needed.

### Building the Windows Installer

If you want to properly install the app, you can build the installer. Unlike the other projects, this one requires .NET Framework 4.8. This is because it's built with [WixSharp](https://github.com/oleg-shilo/wixsharp), which in turn is based on [the WiX toolset](https://wixtoolset.org), and as of version 3.11.2, WiX doesn't support .NET Core or .NET.

Simply run the build, and it will generate the MSI installer in the project's `bin` folder. Before the build, it calls `dotnet publish` to use its output.


# About

Keyboard Switch: version 3.0. Created by [Tolik Pylypchuk](https://github.com/TolikPylypchuk).

## Acknowledgements

Icon made by [Smashicons](https://smashicons.com/) from [www.flaticon.com](https://www.flaticon.com/).

The UI for the settings app was created using [Avalonia](https://avaloniaui.net/) with [ReactiveUI](https://www.reactiveui.net/).

Docs are built using [GitBook](https://www.gitbook.com).

## Changelog

### [v3.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v3.0) (4 August 2020)

* A completely rewritten app based on .NET Core and working as a truly UI-less app instead of an app with a hidden window
* The settings are now a separate app written with Avalonia instead of WPF
* Tray icon was removed
* Added the ability to switch between multiple layouts of the same language (e.g. QWERTY and Dvorak for English)
* Instant switching mode is not experimental anymore and enabled by default
* Added the ability to auto-configure character mappings
* Added checking for updates

### [v2.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v2.1) (1 April 2018)

Minor bug fixes

### [v2.0](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v2.0) (13 January 2018)

* Brand new installer for the app
* Instant switching mode
* Updated readme
* Updated configuration
* Minor UI updates
* Minor bug fixes

### [v1.1](https://github.com/TolikPylypchuk/KeyboardSwitch/releases/tag/v1.1) (somewhere in 2015)

Minor bug fixes

### v1.0 (somewhere in 2015)

All the basic functionality:

* Switching text
* Starting at system startup
* Tray icon

## License

MIT License

Copyright (c) 2015 Anatoliy Pylypchuk

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


