Skip to content

Instantly share code, notes, and snippets.

@drmfinlay
Created December 17, 2020 13:08
Show Gist options
  • Save drmfinlay/69aa81910dd196619f1229cc16909fa4 to your computer and use it in GitHub Desktop.
Save drmfinlay/69aa81910dd196619f1229cc16909fa4 to your computer and use it in GitHub Desktop.
Module for working around Dragonfly issues with custom keyboard layouts
"""
This command module automatically posts input language change request
messages to all top-level windows as a workaround for keyboard layouts where
Dragonfly's Win32 key input doesn't work properly.
Use this module by loading it as a Dragonfly command module.
"""
import time
import win32con
import win32gui
from dragonfly import RecognitionObserver
NORMAL_LAYOUT_HKL = 0x8090809 # HKL for English (UK) - QWERTY
PROCESSING_LAYOUT_HKL = 0xf0c10809 # HKL for English (UK) - Colemak
def postLangChangeReqMsg(hwnd, wParam, lParam):
"""
Post a WM_INPUTLANGCHANGEREQUEST message with the specified parameters.
"""
win32gui.PostMessage(hwnd, win32con.WM_INPUTLANGCHANGEREQUEST, wParam,
lParam)
class HackyObserver(RecognitionObserver):
"""
A hacky recognition observer class for setting the keyboard layout
before and after recognition processing.
"""
def on_recognition(self, words):
# Set the keyboard layout for the foreground window.
hwnd = win32gui.GetForegroundWindow()
# hwnd = win32con.HWND_BROADCAST # Use on Windows versions below 8.
hkl = PROCESSING_LAYOUT_HKL
# print("Setting layout to %08x." % hkl)
postLangChangeReqMsg(hwnd, 0, hkl)
# Wait a moment.
time.sleep(0.001)
def on_post_recognition(self, words):
# Set the keyboard layout for the foreground window.
hwnd = win32gui.GetForegroundWindow()
# hwnd = win32con.HWND_BROADCAST # Use on Windows versions below 8.
hkl = NORMAL_LAYOUT_HKL
# print("Setting layout to %08x." % hkl)
postLangChangeReqMsg(hwnd, 0, hkl)
# Wait a moment.
time.sleep(0.001)
# Register the observer.
observer = HackyObserver()
observer.register()
# Unload function which will be called by natlink at unload time.
def unload():
global observer
if observer:
observer.unregister()
observer = None
@QXD-me
Copy link

QXD-me commented Dec 27, 2020

I made some minor edits (I think processing and normal were the wrong way around), but it seems to be working.
Thanks :)

https://gist.github.com/QXD-me/3399bceb59e30d36ebd75d8877ec03ab

@drmfinlay
Copy link
Author

Okay then. Glad I could help :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment