Ubuntu – How to define AutoKey shortcut which sends the same keystroke to the window with certain title

autokeygnu-screen

How to define a global shortcut Ctrl+a 1 with AutoKey which sends the same keystroke Ctrl+a 1 to the window with title 'gnu screen' ? If there is no such titled window it should show a popup message "Couldn't find destination window".

Best Answer

  1. Install libnotify-bin which provides notify-send

    sudo apt-get install libnotify-bin
    
  2. Create new script:

    import time
    import subprocess
    
    #no need
    #keyboard.release_key("<ctrl>")
    
    # wait_for_keypress does not return any thing to distinguish between target key pressed or timeout reached.
    # So if time is less than the timeout then it was key press.
    start_time = time.time()
    keyboard.wait_for_keypress("1", timeOut=1)
    if (time.time()-start_time < 0.9):
        time.sleep(0.2)
        window.activate("gnu screen")
        time.sleep(0.1)
        active_title = window.get_active_title()
        # if it doesn't get same title, then no window titled as gnu screen
        # it sends a notify message otherwise send the key sequence.
        if (active_title == "gnu screen"):
            keyboard.press_key("<ctrl>")
            keyboard.send_key("a")
            keyboard.release_key("<ctrl>")
            keyboard.send_key("1")
        else:
            subprocess.Popen(['notify-send', "Couldn't find destination window"])
    
  3. Setup its hot key as: Ctrl+a

To trigger it: Ctrl+a then 1 (in <1sec)


Debug

  1. Launch X Event Tester in separate terminal window

    xev -event keyboard
    
  2. Check it's window title, mine shows Event Tester

    $ wmctrl -l
    0x03000012 -1       N/A Desktop — Plasma
    0x030000c1 -1       N/A Desktop — Plasma
    0x0300001b -1       N/A Plasma
    0x06a00098  0        PC User User - Ask Ubuntu - Mozilla Firefox
    0x01a00067  0       N/A user : screen
    0x01a000cd  0       N/A user : xev
    0x04600001  0       N/A Event Tester
    0x01e0015d  0        PC AutoKey
    
  3. Modify script to target Event Tester window.

    import time
    import subprocess
    
    start_time = time.time()
    keyboard.wait_for_keypress("1", timeOut=1)
    if (time.time()-start_time < 0.9):
        time.sleep(0.2)
        window.activate("Event Tester")
        time.sleep(0.1)
        keyboard.press_key("<ctrl>")
        keyboard.send_key("a")
        keyboard.release_key("<ctrl>")
        keyboard.send_key("1")
    
  4. If xev receives the key sequence. Its output should be some thing similar to:

    KeyPress event, serial 34, synthetic NO, window 0x4600001,
        root 0xb2, subw 0x0, time 55057700, (1053,140), root:(945,303),
        state 0x0, keycode 105 (keysym 0xffe4, Control_R), same_screen YES,
        XLookupString gives 0 bytes: 
        XmbLookupString gives 0 bytes: 
        XFilterEvent returns: False
    
    KeyPress event, serial 34, synthetic YES, window 0x4600001,
        root 0xb2, subw 0x0, time 0, (1,1), root:(1,1),
        state 0x0, keycode 38 (keysym 0x61, a), same_screen YES,
        XLookupString gives 1 bytes: (61) "a"
        XmbLookupString gives 1 bytes: (61) "a"
        XFilterEvent returns: False
    
    KeyRelease event, serial 35, synthetic YES, window 0x4600001,
        root 0xb2, subw 0x0, time 0, (1,1), root:(1,1),
        state 0x0, keycode 38 (keysym 0x61, a), same_screen YES,
        XLookupString gives 1 bytes: (61) "a"
        XFilterEvent returns: False
    
    KeyRelease event, serial 35, synthetic NO, window 0x4600001,
        root 0xb2, subw 0x0, time 55057701, (1053,140), root:(945,303),
        state 0x4, keycode 105 (keysym 0xffe4, Control_R), same_screen YES,
        XLookupString gives 0 bytes: 
        XFilterEvent returns: False
    
    KeyPress event, serial 35, synthetic YES, window 0x4600001,
        root 0xb2, subw 0x0, time 0, (1,1), root:(1,1),
        state 0x0, keycode 10 (keysym 0x31, 1), same_screen YES,
        XLookupString gives 1 bytes: (31) "1"
        XmbLookupString gives 1 bytes: (31) "1"
        XFilterEvent returns: False
    
    KeyRelease event, serial 35, synthetic YES, window 0x4600001,
        root 0xb2, subw 0x0, time 0, (1,1), root:(1,1),
        state 0x0, keycode 10 (keysym 0x31, 1), same_screen YES,
        XLookupString gives 1 bytes: (31) "1"
        XFilterEvent returns: False
    

Note, I have removed the if condition to check active title. The script activates/raises xev window but the check doesn't find the correct title. I got just the notification message.