Skip to content

[Windows] win32_event_filter returning False prevents on_press/on_release callbacks from receiving the event #679

Description

@redstoneleo

Description

When using keyboard.Listener on Windows, if you provide a win32_event_filter and return False to suppress a specific key from reaching the OS, that key is ALSO incorrectly hidden from the Listener's own

on_press and

on_release callbacks.

This makes it impossible to implement "selective key suppression" (e.g., intercepting a specific physical key to use as a macro trigger while allowing all normal typing to pass through, and then handling the macro logically inside

on_press).

To work around this currently, developers are forced to fire their custom logic directly inside the win32_event_filter thread, which is dangerous as it risks stalling the global Windows keyboard hook.

Minimal Reproducible Example

from pynput import keyboard

# For this example, we want to suppress the "Right Arrow" key from the OS,
# but still want to detect it in Python to trigger some application logic.
TARGET_VK = 0x27  # VK_RIGHT

def win32_event_filter(msg, data):
    if data.vkCode == TARGET_VK:
        # Return False to suppress this key from being sent to the OS/other apps (Works)
        return False
    return True

def on_press(key):
    # BUG: If the key was suppressed in win32_event_filter, 
    # this callback is NEVER fired for it!
    print(f"Python on_press received: {key}")

def on_release(key):
    # This also never fires for the suppressed key.
    if key == keyboard.Key.esc:
        return False

print("Press the Right Arrow key. Notice how it is suppressed from the OS, but also disappears from on_press.")
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release,
        win32_event_filter=win32_event_filter) as listener:
    listener.join()

Expected behavior

When win32_event_filter returns False, it should suppress the event from propagating to the operating system/other applications (i.e., return 1 from the Windows Hook), BUT it should still dispatch the event to the

on_press and

on_release callbacks so the Python application can handle the key it intentionally intercepted.

Actual behavior

The key is suppressed from the OS successfully, but

on_press and

on_release are never triggered for that key.

Environment

  • OS: Windows 10/11
  • pynput version: (You can fill in your actual version here, usually 1.7.6 or latest)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions