Skip to content

Fix macOS keyboard layout issues with Unicode typing#947

Open
jmpnop wants to merge 1 commit intoasweigart:masterfrom
jmpnop:fix/macos-keyboard-layout-unicode
Open

Fix macOS keyboard layout issues with Unicode typing#947
jmpnop wants to merge 1 commit intoasweigart:masterfrom
jmpnop:fix/macos-keyboard-layout-unicode

Conversation

@jmpnop
Copy link

@jmpnop jmpnop commented Dec 22, 2025

Problem

PyAutoGUI currently types incorrect characters on macOS when using non-US keyboard layouts (Russian, German, Dvorak, etc.) because it sends virtual key codes that get mapped by the active keyboard layout.

Example:

  • Keyboard layout: Russian
  • Code: pyautogui.write("test")
  • Current behavior: Types "еуіе" (Russian characters)
  • Expected: Types "test"

This has been reported in:

Solution

This PR fixes the issue by using CGEventKeyboardSetUnicodeString from macOS's Quartz framework for printable characters, while maintaining the existing key code approach for special keys.

Changes

  1. Added _isPrintableChar(key): Distinguishes printable characters from special keys (arrows, modifiers, function keys, etc.)
  2. Added _typeUnicodeChar(char): Types characters using layout-independent Unicode method via CGEventKeyboardSetUnicodeString
  3. Modified _normalKeyEvent(): Routes printable characters through Unicode typing for 'down' events, skips 'up' events for printable chars (Unicode method handles both)

Why This Approach?

  • Backward compatible: No API changes, existing code works unchanged
  • Scoped: Only affects macOS (_pyautogui_osx.py, ~50 lines of code)
  • Preserves special keys: Enter, Tab, arrows, modifiers still use key codes as before
  • Layout independent: Works with any keyboard layout (US, Russian, German, Dvorak, etc.)
  • Non-breaking: No changes to other platforms or public API

Testing

Tested On

  • OS: macOS 14.6 (Sonoma/Sequoia)
  • Python: 3.14
  • Keyboard layouts: US QWERTY, Russian

Test Results

Test Case Result
Basic text typing with Russian layout ✅ Correct English output
Special characters (@, ., -, etc.) ✅ Works correctly
Bundle IDs (com.example.app) ✅ Types correctly
Special keys (Enter, Tab, arrows) ✅ Work as before
Keyboard shortcuts (Cmd+A, Cmd+C) ✅ Work as before
Shift characters (uppercase, symbols) ✅ Work correctly

Test Code

import pyautogui

# All of these now work correctly with Russian keyboard layout active
pyautogui.write("Hello World")
pyautogui.write("test@example.com")
pyautogui.write("com.lukilabs.lukiapp")
pyautogui.press('enter')
pyautogui.hotkey('command', 'a')

Impact

This fix will benefit users who:

  • Use macOS with non-US keyboard layouts
  • Need to type English text programmatically regardless of active layout
  • Automate GUI testing across different language settings
  • Work in international environments with multiple keyboard layouts

Based on the issue tracker, this affects many users across different languages and layouts.

Backward Compatibility

All existing PyAutoGUI code continues to work

  • No API changes
  • No breaking changes to function signatures
  • Only affects macOS platform
  • Special keys maintain current behavior
  • Other platforms unaffected

Technical Details

The fix uses macOS's CGEventKeyboardSetUnicodeString API which sets the Unicode representation of characters directly on keyboard events, bypassing the keyboard layout mapping that was causing the issue.

Before:

  1. PyAutoGUI sends key code for physical key 'C' (0x08)
  2. macOS applies Russian layout mapping
  3. System outputs 'с' (Cyrillic)

After:

  1. PyAutoGUI detects 'c' is printable
  2. Creates keyboard event with Unicode string "c"
  3. System outputs 'c' regardless of layout

Special keys still use key codes (arrows need physical key position, not Unicode).

Additional Notes

I'm happy to:

  • Add more tests if needed
  • Test on additional macOS versions (Ventura, Monterey if access is needed)
  • Make any requested changes
  • Add documentation if needed
  • Maintain this code if issues arise

This is a real-world fix that I've been using successfully. I wanted to contribute it back to help others facing the same issue.

Thank you for maintaining PyAutoGUI! It's an incredibly useful library.

This fix resolves issues where PyAutoGUI would type incorrect characters
when using non-US keyboard layouts on macOS (Russian, German, Dvorak, etc.).

Changes:
- Add _isPrintableChar() to distinguish printable chars from special keys
- Add _typeUnicodeChar() using CGEventKeyboardSetUnicodeString for
  layout-independent character input
- Modify _normalKeyEvent() to route printable characters through Unicode
  typing while maintaining key code approach for special keys

This approach:
- Is backward compatible (no API changes)
- Only affects macOS (_pyautogui_osx.py)
- Preserves existing behavior for special keys
- Works with any keyboard layout

Fixes asweigart#46, asweigart#122
Related to asweigart#137
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants