Skip to content

FR 02 Fonctionnement

Captain FLAM edited this page Aug 27, 2026 · 2 revisions

⚙️ Fonctionnement de l'exécutable

Ce document décrit le comportement runtime de Copilot_Key+.exe (Sources/CopilotKey.c) : comment il démarre, comment il détecte la touche Copilot, comment il la transforme, et comment il se configure/s'arrête. (Pour compiler ce même code, voir 🛠️ 03-Build-Compilation.md.)

🚦 Les 3 modes de lancement (WinMain)

Le même .exe se comporte différemment selon ses arguments de ligne de commande :

Commande Fonction Rôle
Copilot_Key+.exe (sans argument) mode par défaut 👻 s'installe en résident (voir plus bas)
Copilot_Key+.exe -config RunInstall() 🎛️ assistant interactif en console (capture + réglages)
Copilot_Key+.exe -quit RunQuit() 🛑 demande à l'instance résidente de s'arrêter proprement

👻 Mode résident (par défaut)

  1. Instance unique : CreateMutexA("Global\CopilotKeyPlus") - si le mutex existe déjà, l'exe se termine aussitôt (code 0), pas de doublon possible.
  2. Priorité haute (HIGH_PRIORITY_CLASS) pour limiter la gigue du hook clavier sous forte charge CPU, sans les risques système de REALTIME_PRIORITY_CLASS.
  3. Fenêtre cachée de classe CopilotKeyPlusCtl (HWND_MESSAGE) : sert de cible pour -quit (via WM_CLOSE) et, en mode HID, reçoit les événements WM_INPUT.
  4. Chargement des réglages (LoadRegistrySettings) depuis HKCU\Software\CopilotKey+ (voir plus bas).
  5. Pose du hook clavier bas niveau : SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, ...)
    • intercepte toutes les touches du système avant Windows.
  6. Boucle de messages standard (GetMessage/DispatchMessage) jusqu'à WM_QUIT (déclenché par -quit) ou WM_ENDSESSION (fermeture de session Windows) - dans les deux cas, relâche proprement la touche Copilot synthétique si elle était enfoncée, puis retire le hook et le mutex.

🗄️ Réglages stockés en registre (HKCU\Software\CopilotKey+)

Valeur Type Contenu
Mode DWORD 0 = désactivée, 1 = CTRL droit (défaut), 2 = Menu contextuel
Arrows DWORD 1 = remap flèches actif (défaut), 0 = désactivé
Signature REG_SZ Salve de scancodes apprise (chemin scancode classique)
HIDconsumer REG_SZ Usage HID Consumer en hex (chemin touche matérielle dédiée) - mutuellement exclusif avec Signature
Burst DWORD Fenêtre de confirmation de la salve (ms), mesurée à l'install
Grace DWORD Fenêtre de grâce flèches (ms), calibrée à l'install

⌨️ Détection de la touche Copilot : deux chemins possibles

Chemin 1 - salve de scancodes classique (la grande majorité des claviers)

Il n'existe pas de table figée par constructeur : chaque clavier envoie une combinaison différente à l'appui de Copilot (Win+C, Win+Maj+F23, Win+Ctrl+F23, etc. - table indicative en tête de CopilotKey.c, non utilisée par le code). La combinaison réelle (jusqu'à MAX_SIG = 6 touches) est apprise à l'installation (-config) et stockée dans Signature.

Chaque touche de la signature est classée en deux catégories (SigSlot.modifier, voir IsSafeModifierScanCode) :

  • Modificateur "sûr" (Shift/Ctrl/Alt gauche ou droit) : scancode universel, transmis immédiatement à Windows sans latence (usage normal préservé : frappe rapide, jeu...). Son état est juste suivi pour savoir si la salve est complète.
  • Touche "retenue" (typiquement Win, ou une touche F23/F24 peu utilisée seule) : avalée (non transmise) et mise en attente de confirmation.

Machine à états (burstState : IDLEPENDINGACTIVE) dans KeyboardProc :

  1. IDLE : rien ne se passe.
  2. Une touche "retenue" de la signature s'enfonce → PENDING, démarre un timer g_pendingWindowMs (mesuré/doublé à l'install, borné 25–200 ms).
  3. Si toutes les touches de la signature sont "bas" avant expiration du timer (TryConfirmBurst) → ACTIVE : les modificateurs "sûrs" déjà transmis sont neutralisés ponctuellement (un KEYUP synthétique) pour que l'application au premier plan reçoive une touche Copilot propre (ex. CTRL droit seul, pas Maj+CTRL droit) - sauf un modificateur déjà tenu avant le début de la salve (preHeld), qui reste transmis normalement : c'est ce qui permet Copilot + Maj + Flèche quand Maj fait partie de la signature matérielle de la machine (cf. avertissement README sur l'ordre d'appui). Une fois ACTIVE, SendCopilotKey(TRUE) injecte la vraie touche cible (CTRL droit par scancode, ou Menu contextuel par code virtuel) via SendInput.
  4. Si le timer expire avant complétion (PendingTimeoutProcAbortPendingBurst) : les touches avalées jusque-là sont rejouées telles quelles vers l'OS - elles redeviennent des touches "normales".
  5. Au relâchement de la dernière touche encore tenue de la signature (EndActiveCombo) : relâche la touche Copilot synthétique, restaure vers l'OS l'état réel des modificateurs neutralisés, retour à IDLE.

Chemin 2 - touche Copilot matérielle dédiée (HID Consumer, Windows 11 23H2+)

Certains claviers récents envoient un usage HID Consumer Page 0x0C (usage 0x0D8 typiquement) au lieu d'une salve de scancodes classique - invisible pour WH_KEYBOARD_LL. Repli automatique : si la capture scancode ne détecte rien à l'installation, le programme écoute en Raw Input (RegisterRawInputDevices

  • WM_INPUT dans HiddenWndProc) et apprend dynamiquement l'usage réellement vu (jamais figé en dur - un usage différent de 0x0D8 fonctionnerait quand même). Ce mode n'active le Raw Input que si HIDconsumer est présent en registre : zéro overhead pour les autres utilisateurs. Pas de machine à états temporisée ici : down/up de l'usage HID pilotent directement SendCopilotKey.

⚠️ Chemin non testé sur matériel réel (cf. avertissement README) - si Windows intercepte la touche avant Raw Input, aucun repli n'existe.

🧭 Remap des flèches (Copilot + Flèches)

Tant que la combinaison est ACTIVE - ou dans une fenêtre de grâce g_arrowGraceMs après un relâchement naturel de la salve (certains claviers relâchent leur salve matérielle après quelques centaines de ms indépendamment de la tenue physique réelle, cf. calibration Grace) - les flèches ←/→/↑/↓ sont interceptées et remplacées par Home/End/PgUp/PgDn (scancodes injectés via SendInput). La touche Copilot synthétique est brièvement relâchée puis restaurée autour de l'injection de la flèche, pour éviter qu'elle ne se combine avec CTRL droit. Les modificateurs physiques (Maj/Ctrl) restent transmis normalement en parallèle par Windows, d'où les combinaisons sélection/document entier décrites dans le README (« Copilot MULTI »).

🎛️ Mode -config (RunInstall)

Assistant interactif en console (alloue une console même si l'exe est en mode GUI) :

  1. Choix de la langue (FR par défaut).
  2. Capture de la signature : jusqu'à 4 essais, chacun avec un hook WH_KEYBOARD_LL dédié (CaptureOneAttempt) qui enregistre toutes les touches vues pendant l'appui puis attend un silence de CAPTURE_QUIET_MS (700 ms) ou un timeout de CAPTURE_TIMEOUT_MS (5 s). Si aucune touche scancode n'est vue, tente la capture HID Consumer (CaptureOneHidAttempt). Deux essais consécutifs doivent produire le même ensemble de touches (même type scancode/HID) pour confirmer la signature - sinon on recommence.
  3. Avertissements si la combinaison ne contient que des modificateurs Shift/Ctrl/Alt (aucune touche distinctive → détection par l'ancien mécanisme, délai possible), ou si un modificateur arrive après la touche distinctive dans la salve (risque de pollution occasionnelle de la touche synthétique).
  4. Choix du comportement de Copilot seul (CTRL droit / Menu / Rien).
  5. Activation ou non du remap flèches (O/N).
  6. Si activé : calibration de la fenêtre de grâce - demande à l'utilisateur de tenir Copilot ~2,5 s puis de relâcher normalement, pour distinguer un auto-relâchement matériel d'un relâchement volontaire (CalibrateArrowGrace).
  7. Écriture de tous les réglages dans HKCU\Software\CopilotKey+ (avec nettoyage des résidus de l'autre chemin, scancode ↔ HID, en cas de réinstallation après changement de clavier).
  8. Relance l'instance résidente : envoie -quit à l'instance en cours (si présente) puis relance un nouveau process pour appliquer immédiatement les réglages - c'est pour ça qu'un rebuild + -config (ou un simple changement de réglage) prend effet tout de suite, sans étape manuelle côté utilisateur final (contrairement à un rebuild Release brut sans -config, qui reste chargé en mémoire tant que -quit n'a pas été envoyé).

🛑 Mode -quit (RunQuit)

Cherche la fenêtre cachée CopilotKeyPlusCtl (FindWindowExA) et lui poste un WM_CLOSE - pas de kill par nom de process. HiddenWndProc traduit ce WM_CLOSE en PostQuitMessage(0), ce qui fait sortir la boucle de messages de l'instance résidente et déclenche l'arrêt propre décrit plus haut. Code retour : 0 si une instance a été trouvée et sollicitée, 1 sinon.

Clone this wiki locally