Programm das einen weiteren Tastaturlayer emuliert.
Auf diesen virtuellen Layer können schwer zu erreichende Tasten oder komplizierte Tastenkombinationen gelegt werden. Dann kann auf den Layer mit einer konfigurierbaren Taste wie z. B. CapsLock gewechselt werden, während diese gehalten wird. Siehe [_features] für mehr Details.
Wichtig
|
Dieses Projekt ist archiviert, da ich eine für mich einfachere Lösung gefunden habe CapsLock mit Esc zu tauschen (PowerToys Keyboard Manager) und ich somit keinen Use Case mehr für dieses Projekt habe. |
Anmerkung
|
Leider funktioniert die Anzeige von AsciiDoc-Dokumenten in GitHub
nicht wirklich gut, deshalb sollte die Dokumentation besser lokal angesehen
werden. Siehe die Build Anweisungen fĂĽr Generelle Dokumentation .
|
Wichtig
|
Diese Funktionalität gibt es sehr ähnlich bereits in Linux. Siehe Caps + hjkl as arrow keys. Deshalb werden durchgestrichene Features nicht mehr implementiert beziehungsweise weiter entwickelt werden. |
Erklärung aller Features und generelle Fortschrittsübersicht.
- Konfigurierbare Layer-Umschalttaste
-
Die Taste welche gehalten wird, um auf den virtuellen Layer zu schalten ist frei wählbar.
- Standarttastaturkombination beim leeren Umschalten
-
Wenn die Layer-Umschalttaste losgelassen wird ohne eine Tastenkombination auszulösen kann optional eine Standarttastenkombination gesendet werden.
NĂĽtzlich um z. B. ein weiteres Escape auf CapsLock zu legen und somit die eigentliche Funktionsweise von CapsLock komplett zu Ersetzen.
- Sprach- und Layout unabhängige Implementation
-
Alle Tasten werden daran erkannt welchen Text sie produzieren, wenn sie einzeln gedrückt werden. Das bedeutet egal welche Kombination von Ausgabe verändernden Tasten mit gedrückt werden, es wird nur der Basistext erkannt.
Beispiel: Die2
-Taste (deutsches Layout)2 =
2
⇒2
erkannt
Shift+2 ="
⇒2
erkannt
Strg+Alt+2 =²
⇒2
erkanntDeadkeys also Tasten die nur in Kombination mit einer anderen Taste auch Text produzieren und Tasten welche Unicode Symbole produzieren werden auch erkannt.
Beispiel: Deadkeys und Unicode´ =
[Keine Ausgabe]
⇒´
erkannt
^ =[Keine Ausgabe]
⇒^
erkannt
ä =ä
⇒ä
erkannt
ĂĽ =ĂĽ
⇒ü
erkannt - Textbasierte als auch graphische Konfigurationsmöglichkeiten
-
Das Projekt stellt einen visuellen Editor fĂĽr die Konfiguration des virtuellen Layers bereit. NatĂĽrlich kann auch die TOML-Datei direkt bearbeitet werden und dann fĂĽr das Starten des virtuellen Layers mit der Cli verwendet werden.
- Starten mit dem System (nur auf Windows)
-
Startet AKL automatisch mit dem System. Es macht wenig Sinn diese Funktionalität für Linux bereit zu stellen, da es dort zu viele verschiedene Möglichkeiten gibt und die Entscheidung darüber den Benutzer überlassen werden sollte.
- Livereload der Konfiguration
-
Es gibt die Möglichkeit den virtuellen Layer automatisch neu zu starten, sobald manuelle Änderungen an der Konfigurationsdatei vorgenommen worden sind. Siehe Cli Optionen: [_verfügbare_optionen_englisch]
Allgemeiner Fortschritt des Projekts ohne die genauen Features direkt zu nennen, stattdessen wird die Fertigstellung der Komponenten betrachtet.
-
âś“ AKL.Common Abstraktion
-
âś“ Windows Prototyp
-
âś“ akl-core-system-lib Windows Implementation
-
âś“ AKL.Cli Implementation
-
❏ Linux Prototyp (Ohne Root Zugriff und ohne
plugdev
-Gruppe) -
❏ akl-core-system-lib Linux Implementation
-
âś“ Starten mit dem System unter Windows
-
❏ AKL.Gui
Anmerkung
|
Die Implementationen wurden mit der Hilfe von Prototypen entwickelt, damit die benötigten Funktionen (Tastaturevents blockieren und Tastenanschläge simulieren) einzeln herausgefunden werden können. |
Das Projekt Another Keyboard Layer ist in GUI, Cli, Common und Native / Core Komponenten auf geteilt, wobei nur die Native / Core Library in Rust geschrieben wird, da die Kommunikation mit Low Level Apis in C# zwar möglich aber sehr mühsam ist.
Außerdem soll während der Verwirklichung des Projekts GUI-Entwicklung und Interfacing mit Native Bibliotheken in C# besser gelernt werden.
Anmerkung
|
Das Interfacing mit Rust ist sehr viel einfacher, da die Bindings fĂĽr C# automatisch mit csbindgen generiert werden. |
@startuml !theme reddress-darkblue node "Operating System" { interface "Raw keyboard events" as keyboard note bottom of keyboard Implementation is os dependent. end note } component "Core Library (""akl-core-system-library"")" as core interface "Toml Configuration" as config component "Shared Functionality (""AKL.Common"")" as common component "Main User Interface (""AKL.Gui"")" as gui component "Basic Cli Wrapper (""AKL.Cli"")" as cli gui --> common : uses cli --> common : uses common --> core : configures, starts and stops config <- common : writes and reads note left of core Implements the configurable virtual layer. end note core --> keyboard : interacts with @enduml
Der Kern wird in Rust geschrieben und wird direkt mit dem jeweiligen Betriebssystem interagieren, um global Tastaturevents abzuhören und wie konfiguriert zu verändern. Außerdem wird der Kern ein C Interface bereit stellen und im Build-Vorgang automatisch CSharp Bindings für dieses generieren.
Darstellung der Verarbeitung der Tastaturanschläge unabhängig vom Betriebssystem.
@startuml !theme reddress-darkblue enum Key { Text(char) Virtual(VirtualKey) } enum Action { Press Release } class Event { key: Key action: Action } enum ResponseAction { Nothing Block ReplaceWith(KeyCombination) } class EventProcessor { switch_key: Key, default_combination: Option<KeyCombination>, mappings: HashMap<KeyCombination, KeyCombination>, currently_pressed: Vec<Key>, block_events: bool, key_combination_executed: bool, +process(event: Event) -> ResponseAction } class NativeInputHook { {static} processor: EventProcessor ## native_input_handling ## } note right of NativeInputHook Zuständig für das Parsen von Rohevents und Ausführung von aus dem Processing entstehenden ResponseActions. end note Event *- Key Action -* Event EventProcessor - ResponseAction EventProcessor -- Event NativeInputHook -- EventProcessor : uses to process events @enduml
@startuml !theme reddress-darkblue start if (Action is **press**?) then (yes) if (Key is switch key?) then (yes) :Set block events = true; :Clear currently pressed keys; :Return block event> detach else (no) endif if (Don't block events?) then (yes) :Return don't change event> detach else (no) endif :Add key to currently pressed keys; :Create key combination from pressed keys; if (Key combination is target for replacement?) then (yes) :Set key combination executed = true; :Remove current key from currently pressed; :Return replace with replacement combination> detach else (no) endif :Return block event> elseif (Action is **release**?) then (yes) if (Key is switch key?) then (yes) :Set block events = false; if (Not key combination executed and default combination is set?) then (yes) :Return replace with default combination> detach else (no) endif :Reset key combination executed flag; :Return block event> detach else (no) if (Key in currently pressed?) then (yes) :Remove key from currently pressed keys; if (Block events is true?) then (yes) :Return block event> detach else (no) endif else (no) endif endif :Return don't change event> else (invalid action data) :Skip event; detach endif stop @enduml
Die graphische Benutzerschnittstelle bietet eine Möglichkeit den virtuellen Layer komplett zu konfigurieren und diesen zu aktivieren oder zu deaktivieren. Zu konfigurierende Werte sind unter anderem der Umschalter, die Taste welche bei schnellem Drücken des Umschalters ohne eine weitere Taste simuliert werden soll und die eigentlichen Mappings. Des Weiteren dient dieses Modul dem Erlernen der GUI Programmierung mit dem Avalonia Framework, welches von der Struktur sehr stark WPF ähnelt.
@startsalt !theme reddress-darkblue scale 2 { [X] Start with System Switch Key | "CapsLock " Default Combination | "Escape " . {SI {# **Target** | **Replacement** "h" | "ArrowLeft" "j" | "ArrowDown" "k" | "ArrowUp" "l" | "ArrowRight" " " | " " } } [ <&plus> Add mapping ] . [ <&reload> Restart Virtual Layer ] | [ <&hard-drive> Save configuration ] } @endsalt
Zusätzlich zur graphischen Schnittstelle soll die textbasierte Benutzerschnittstelle ein kleiner Wrapper um den Kern sein, der diesen nur mit Hilfe der gespeicherten Konfiguration vom GUI initialisiert, außerdem sollte für die Implementierung, Microsofts eigens für das Entwickeln von CLIs erstellte Bibliothek System.CommandLine verwendet werden.
@startuml !theme reddress-darkblue start :Parse cli arguments; if (Config path overriden?) then (yes) :Use custom config path; else (no) :Use default config path; endif if (Config file exists?) then (no) if (Custom path set?) then (yes) :Print error message> :Exit program early; detach else (no) :Save default configuration; endif else (yes) endif :Load configuration file; if (Parsing config sucessfull?) then (no) :Print error message with cause> :Exit program early; detach else (yes) if (Live reload activated?) then (yes) :Start file watcher in background thread; :Create callback for updating the virtual layer; else (no) endif :Start virtual layer; :Block until receiving Ctrl + C; endif stop @enduml
Dieses Modul sollte das Parsen und Schreiben der Konfigurationsdatei als auch
die Interaktion mit akl-core-system-lib
ĂĽbernehmen, damit keine Logik
unnötigerweise dupliziert wird.
Nachdem Verarbeiten der Konfiguration sollten die Einstellungen falls nötig automatisch angewendet werden z. b. Autostart An / Aus.
Anmerkung
|
Die Konfiguration soll im TOML format gespeichert werden und in C# mit Tomlyn verarbeitet werden. |
@startuml !theme reddress-darkblue enum VirtualKeyCode { Space, Tab, Return ... } note left of VirtualKeyCode::... Steht fĂĽr die restlichen Special / Named Keys, allerdings macht es keinen Sinn diese hier aufzulisten. end note enum KeyKind { Text, Virtual } class Key { {field} -VirtualKeyCode? virtualKey {field} -Char? textKey {field} -KeyKind kind {static} {method} +Key TryParse(string raw) } class KeyCombination { {field} -Key[] keys; {static} {method} +KeyCombination TryParse(string raw) } note top of KeyCombination Jede Tastenkombination kann maximal aus 4 Tasten bestehen. Leider gibt es keinen ergonomischen Weg dies in C# Klassen darzustellen. end note class AklConfiguration { {field} -TomlAklConfiguration origin; {field} +bool Autostart {field} +Key SwitchKey {field} +KeyCombination? DefaultCombination {field} +Dictionary<KeyCombination, KeyCombination> Mappings } note left of AklConfiguration::TomlAklConfiguration Internes Model fĂĽr die De-/Serialization in Toml mit Tomlyn. end note class VirtualLayer { {field} +AklConfiguration Configuration {method} +Update() } class AklConfigurationProvider { {field} -FileInfo file {field} -AklConfiguration configuration {static} {method} +AklConfigurationProvider LoadFromFile(FileInfo file) {method} +AklConfiguration GetConfiguration() {method} +void SaveToFile() } Key *-- VirtualKeyCode Key *-- KeyKind KeyCombination o-- Key AklConfiguration o- KeyCombination AklConfiguration o- Key AklConfigurationProvider --> AklConfiguration : loads and saves VirtualLayer *-- AklConfiguration : needs @enduml
Das Gui und die Cli können mit dotnet publish -c Release
fĂĽr die eigene
Platform gebaut werden. Wenn man die Option --os <OS>
am Ende hinzufĂĽgt,
kann man fĂĽr die jeweils andere Platform bauen (gĂĽltige Werte sind win
/
linux
), allerdings wird empfohlen das <OS> immer
anzugeben.
$ dotnet publish -c Release --os win
$ dotnet publish -c Release --os linux
Wichtig
|
Support für Linux wurde eingestellt, weil es nicht möglich ist ohne Root-Berechtigung Keyboard-Events beliebig zu verändern / zu schicken und dass das wichtigste Feature für die Linux-Version gewesen wäre. |
Je nach Präferenz kann Dokumentation lokal oder auch mit Docker generiert werden. Die folgenden Befehle generieren dieses Dokument im HTML und PDF format, außerdem wird die Manpage für das Command-line Interface erstellt.
$ ./build-documentation.py
$ ./build-documentation.py with-docker
Die Dokumentation fĂĽr die akl-core-system-lib
kann mit folgenden Befehl
generiert werden.
$ cargo doc --document-private-items --no-deps --target x86_64-pc-windows-gnu
Die folgende Konfiguration sollte dem Benutzer über das Gui möglich sein, allerdings könnte er die Datei auch direkt verändern und das Programm mit der Cli starten.
link:AKL.Common/default-config.toml[role=include]
Diese Software ist lizenziert unter der Apache License, Version 2.0.
Sofern nicht ausdrücklich anderes angeben, wird jeder Beitrag der absichtlich für die Aufnahme in dieses Werk eingereicht wird, wie in der Apache-2.0-Lizenz definiert, ohne zusätzliche Bedingungen oder Konditionen wie oben lizenziert.
Diese Software verwendet die folgenden Bibliotheken unter Einhaltung der dazugehörigen Lizenzvereinbarungen.
Bibliothek | Lizenz |
---|---|
Bibliothek | Lizenz |
---|---|
Bibliothek | Lizenz |
---|---|
Apache-2.0 oder MIT |
|
BSD-3, Apache-2.0 oder MIT |
|
Apache-2.0 oder MIT |
|
Apache-2.0 oder MIT |
|
Apache-2.0 oder MIT |
|
Apache-2.0 oder MIT |