pythonlinuxkeyboard-shortcutskeyboard-eventspynput

pynput library not working as expected in Python to press Windows + D key


I'm trying to do what this question asked (this question has no valid answers with functional code using pynput): Press Windows+D with pynput. But, my attempts are not working as expected.

On Linux Ubuntu, pressing Windows + d will minimize all windows, thereby showing the desktop. Doing it again will bring all the windows back as they were.

Here's my code:

import time

from pynput.keyboard import Key, Controller

keyboard = Controller()
SUPER_KEY = Key.cmd

keyboard.press(SUPER_KEY)
# time.sleep(1)
keyboard.press('d')
keyboard.release('d')
keyboard.release(SUPER_KEY)

When I run it, I expect the Windows + d shortcut to be pressed, hiding all windows. Instead, only the Windows key is pressed, which brings up the program launcher search tool, and then a single d is left printed in my terminal, like this:

$ ./pynput_press_Windows+D_to_show_the_desktop.py 
$ d

How do I get this to work?

The reference documentation says (https://pynput.readthedocs.io/en/latest/keyboard.html) that Key.cmd is the "Super" or "Windows" key. I've also tried with Key.cmd_l and Key.cmd_r.

cmd = 0

A generic command button. On PC platforms, this corresponds to the Super key or Windows key, and on Mac it corresponds to the Command key. This may be a modifier.

cmd_l = 0

The left command button. On PC platforms, this corresponds to the Super key or Windows key, and on Mac it corresponds to the Command key. This may be a modifier.

cmd_r = 0

The right command button. On PC platforms, this corresponds to the Super key or Windows key, and on Mac it corresponds to the Command key. This may be a modifier.


Update 4 June 2023: keyboard monitor test program, to ensure Key.cmd + d is correct for my keyboard (it is): modified from https://pynput.readthedocs.io/en/latest/keyboard.html#monitoring-the-keyboard:

from pynput import keyboard

print("Keyboard monitor demo program. Press Esc to exit.")

def on_press(key):
    try:
        print('alphanumeric key {0} pressed'.format(
            key.char))
    except AttributeError:
        print('special key {0} pressed'.format(
            key))

def on_release(key):
    print('{0} released'.format(
        key))
    if key == keyboard.Key.esc:
        # Stop listener
        print("Exiting the program.")
        return False

# Collect events until released
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()

Sample output when I press Super + D:

$ ./pynput_monitor_keyboard.py 
Keyboard monitor demo program. Press Esc to exit.
Key.enter released
special key Key.cmd pressed
alphanumeric key d pressed
'd' released
Key.cmd released

Solution

  • I just want to tie the loose ends on this question.

    As far as I can tell, my code in the question is fine. @Сергей Кох's answer is fine too. There is just a bug in pynput is all, preventing it from working in Ubuntu. Super + D fails, Ctrl + Super + D fails, Ctrl + Alt + D fails.

    I'm on Ubuntu 22.04.2, and even in the X11 window manager (as opposed to Wayland), it still doesn't work.

    Here's my bug report: Bug on Linux: Windows (Super) + D doesn't work

    Here is some valid code that should work. If you have a Mac or Windows, please try it out and leave a comment if this code works or not. Both techniques here should be equally valid. Note: a list of all possible keys is here: https://pynput.readthedocs.io/en/latest/keyboard.html#pynput.keyboard.Key

    import time
    
    from pynput.keyboard import Key, Controller
    
    
    # ========== technique 1 ===========
    # From: https://pynput.readthedocs.io/en/latest/keyboard.html
    print("Trying technique 1")
    
    keyboard = Controller()
    SUPER_KEY = Key.cmd
    with keyboard.pressed(SUPER_KEY):
        keyboard.press('d')
        keyboard.release('d')
    
    
    time.sleep(1.0)
    
    
    # ========== technique 2 ===========
    print("Trying technique 2")
    
    keyboard = Controller()
    SUPER_KEY = Key.cmd
    
    keyboard.press(SUPER_KEY)
    keyboard.press('d')
    keyboard.release('d')
    keyboard.release(SUPER_KEY)
    

    The suggestion was made to try Ctrl + Windows + D. It makes no difference, and also doesn't work due to whatever bug is going on. Here is my test code. Note: I also tried Key.ctrl_l instead of Key.ctrl, and it made no difference.

    import time
    
    from pynput.keyboard import Key, Controller
    
    
    # ========== technique 1 ===========
    # From: https://pynput.readthedocs.io/en/latest/keyboard.html
    print("Trying technique 1")
    
    keyboard = Controller()
    SUPER_KEY = Key.cmd
    
    with keyboard.pressed(Key.ctrl):
        with keyboard.pressed(SUPER_KEY):
            keyboard.press('d')
            keyboard.release('d')
    
    
    time.sleep(1.0)
    
    
    # ========== technique 2 ===========
    print("Trying technique 2")
    
    keyboard = Controller()
    SUPER_KEY = Key.cmd
    
    keyboard.press(Key.ctrl)
    keyboard.press(SUPER_KEY)
    keyboard.press('d')
    keyboard.release('d')
    keyboard.release(SUPER_KEY)
    keyboard.release(Key.ctrl)
    

    Ctrl + Alt + D also works manually, same as the options above, but not with pynput. This code also fails to have any effect. Note that I also tried Key.alt_gr and Key.alt_l in place of Key.alt in the code below, and both of those failed too:

    import time
    
    from pynput.keyboard import Key, Controller
    
    
    # ========== technique 1 ===========
    # From: https://pynput.readthedocs.io/en/latest/keyboard.html
    print("Trying technique 1")
    
    keyboard = Controller()
    
    with keyboard.pressed(Key.ctrl):
        with keyboard.pressed(Key.alt):
            keyboard.press('d')
            keyboard.release('d')
    
    
    time.sleep(1.0)
    
    
    # ========== technique 2 ===========
    print("Trying technique 2")
    
    keyboard = Controller()
    
    keyboard.press(Key.ctrl)
    keyboard.press(Key.alt)
    keyboard.press('d')
    keyboard.release('d')
    keyboard.release(Key.alt)
    keyboard.release(Key.ctrl)
    

    So, for people on Ubuntu, if you want to automate a tool to press Windows + D, use wmctrl or ydotool instead:

    1. I have posted a full demo in my answer here: Ask Ubuntu: How can I write a program to press keys, such as Windows + D, in Wayland? (replace xdotool in Wayland), and
    2. I have written a full article with even more info on my website here: Tutorial: Getting started with ydotool to automate key presses (or mouse movements) in Linux.