src/aoikhotkey/util/sendkey_winos.py
def keys_stroke(
    vks,
    vks_pressed=[],
    key_duration=None,
    key_interval=None,
    modifier_interval=None,
    release_initial_keys=True,
    restore_initial_modifiers=True,
):
    """
    Send keys, without being interfered by previously pressed modifier keys.

    :param vks: Virtual keys to send.

    :param vks_pressed: Virtual keys that are currently pressed.

    :param key_duration: Duration between sending key-down and key-up events \
        for a non-modifier key.

    :param key_interval: Interval between sending events for two consecutive
        non-modifier keys.

    :param modifier_interval: Delay between sending key-down events for two \
        consecutive modifier keys.

    :param release_initial_keys: Whether send key-up events to release \
        non-modifier keys that were pressed before sending the keys. Notice
        initial modifier keys will always be released to avoid interference.

    :param restore_initial_modifiers: Whether send key-down events to press \
        modifier keys that were pressed before sending the keys.

    :return: None.
    """
    # Whether last virtual key is modifier.
    # Initial value being True is required by code at 2NG2A.
    last_vk_is_modifier = True

    # Group list.
    # Each group is a tuple of (modifier_s, non_modifier_s).
    group_s = []

    # Current group's modifier virtual key list
    modifier_s = []

    # Current group's non-modifier virtual key list
    non_modifier_s = []

    # Virtual key index
    vk_idx = 0

    # Virtual key list length
    vks_len = len(vks)

    # While have remaining virtual keys
    while vk_idx < vks_len:
        # Get a virtual key
        vk = vks[vk_idx]

        # Increment the virtual key index
        vk_idx += 1

        # 2NG2A
        # If last virtual key is not modifier,
        # it means the end of a group.
        if not last_vk_is_modifier:
            # Add the group's modifiers and non-modifiers to the group list
            group_s.append((modifier_s, non_modifier_s))

            # Set the modifier virtual key list be empty for next group
            modifier_s = []

            # Set the non-modifier virtual key list be empty for next group
            non_modifier_s = []

        # If the virtual key is modifier
        if vk in _MODIFIER_VKS:
            # Add the virtual key to the modifier virtual key list
            modifier_s.append(vk)

            # Set last virtual key is modifier be True
            last_vk_is_modifier = True

        # If the virtual key is not modifier
        else:
            # Add the virtual key to the non-modifier virtual key list
            non_modifier_s.append(vk)

            # Set last virtual key is modifier be False
            last_vk_is_modifier = False

    # If the modifier or non-modifier virtual key list is not empty
    if modifier_s or non_modifier_s:
        # Add the last group's modifiers and non-modifiers to the group list
        group_s.append((modifier_s, non_modifier_s))

    # Set the modifier virtual key list be None
    modifier_s = None

    # Set the non-modifier virtual key list be None
    non_modifier_s = None

    # Get initial group's modifier and non-modifier virtual key lists
    initial_group = (
        tuple(vk for vk in vks_pressed if vk in _MODIFIER_VKS),
        tuple(vk for vk in vks_pressed if vk not in _MODIFIER_VKS),
    )

    # If need release initial non-modifier keys
    if release_initial_keys:
        # For initial group's each non-modifier virtual key
        for vk in initial_group[1]:
            # Send key-up event
            key_up_sc(vk)

    # Use the initial group as the initial previous group
    previous_group = initial_group

    # Get max group index
    group_idx_max = len(group_s) - 1

    # For the group list's each group
    for group_idx, group in enumerate(group_s):
        # Get previous group's modifiers
        modifier_s_old, _ = previous_group

        # Get current group's modifiers and non-modifiers
        modifier_s_new, non_modifier_s_new = group

        # ----- Press new modifiers -----
        # Get max index of the new modifier list
        vk_idx_max = len(modifier_s_new) - 1

        # For the new modifier list's each virtual key
        for vk_idx, vk in enumerate(modifier_s_new):
            # Send key-down event
            key_dn_sc(vk)

            # If have modifier interval
            if modifier_interval:
                # If the index is not the max index
                if vk_idx != vk_idx_max:
                    # Sleep for modifier interval
                    _time.sleep(modifier_interval)
        # ===== Press new modifiers =====

        # ----- Release old modifiers -----
        # Get the two modifier lists' difference list.
        # The difference list contains the modifiers that should be released.
        modifier_s_diff = _list_diff(modifier_s_old, modifier_s_new)

        # For the difference list's each virtual key
        for vk in modifier_s_diff:
            # Send key-up event.
            #
            # Use `key_up_sc` because `key_up` does not work for DirectInput.
            key_up_sc(vk)
        # ===== Release old modifiers =====

        # ----- Press new non-modifiers -----
        # Get max index of the new non-modifier list
        vk_idx_max = len(non_modifier_s_new) - 1

        # For the new non-modifier list's each virtual key
        for vk_idx, vk in enumerate(non_modifier_s_new):
            # Send key-down event.
            #
            # Use `key_dn_sc` because `key_dn` does not work for DirectInput.
            key_dn_sc(vk)

            # If have key duration
            if key_duration:
                # If the index is not the max index
                if vk_idx != vk_idx_max:
                    # Sleep for key duration
                    _time.sleep(key_duration)

            # Send key-up event
            key_up_sc(vk)
        # ===== Press new non-modifiers =====

        # ----- Release new non-modifiers -----
        # For the new non-modifier list's each virtual key
        for vk in reversed(modifier_s_new):
            # Send key-up event
            key_up_sc(vk)
        # ===== Release new non-modifiers =====

        # Set the previous group be the current group for next group
        previous_group = group

        # If have key interval
        if key_interval:
            # If is not the last group
            if group_idx != group_idx_max:
                # Sleep for key interval
                _time.sleep(key_interval)

    # If need restore initial modifiers after sending the keys
    if restore_initial_modifiers:
        # If the initial group is not the only group
        if previous_group is not initial_group:
            # Get initial group's modifier list
            initial_modifier_s, _ = initial_group

            # Get the max index
            vk_idx_max = len(initial_modifier_s) - 1

            # For initial group's modifier list's each virtual key
            for vk_idx, vk in enumerate(initial_modifier_s):
                # Send key-down event
                key_dn_sc(vk)

                # If have modifier interval
                if modifier_interval:
                    # If the index is not the max index
                    if vk_idx != vk_idx_max:
                        # Sleep for modifier interval
                        _time.sleep(modifier_interval)

    Send keys, without being interfered by previously pressed modifier keys.

    :param vks: Virtual keys to send.

    :param vks_pressed: Virtual keys that are currently pressed.

    :param key_duration: Duration between sending key-down and key-up events \
        for a non-modifier key.

    :param key_interval: Interval between sending events for two consecutive
        non-modifier keys.

    :param modifier_interval: Delay between sending key-down events for two \
        consecutive modifier keys.

    :param release_initial_keys: Whether send key-up events to release \
        non-modifier keys that were pressed before sending the keys. Notice
        initial modifier keys will always be released to avoid interference.

    :param restore_initial_modifiers: Whether send key-down events to press \
        modifier keys that were pressed before sending the keys.

    :return: None.
    
Send keys, without being interfered by previously pressed modifier keys.
Send keys without being interfered by previously pressed modifier keys .
def keys_stroke(
    vks,
    vks_pressed=[],
    key_duration=None,
    key_interval=None,
    modifier_interval=None,
    release_initial_keys=True,
    restore_initial_modifiers=True,
):
    last_vk_is_modifier = True
    group_s = []
    modifier_s = []
    non_modifier_s = []
    vk_idx = 0
    vks_len = len(vks)
    while vk_idx < vks_len:
        vk = vks[vk_idx]
        vk_idx += 1
        if not last_vk_is_modifier:
            group_s.append((modifier_s, non_modifier_s))
            modifier_s = []
            non_modifier_s = []
        if vk in _MODIFIER_VKS:
            modifier_s.append(vk)
            last_vk_is_modifier = True
        else:
            non_modifier_s.append(vk)
            last_vk_is_modifier = False
    if modifier_s or non_modifier_s:
        group_s.append((modifier_s, non_modifier_s))
    modifier_s = None
    non_modifier_s = None
    initial_group = (
        tuple(vk for vk in vks_pressed if vk in _MODIFIER_VKS),
        tuple(vk for vk in vks_pressed if vk not in _MODIFIER_VKS),
    )
    if release_initial_keys:
        for vk in initial_group[1]:
            key_up_sc(vk)
    previous_group = initial_group
    group_idx_max = len(group_s) - 1
    for group_idx, group in enumerate(group_s):
        modifier_s_old, _ = previous_group
        modifier_s_new, non_modifier_s_new = group
        vk_idx_max = len(modifier_s_new) - 1
        for vk_idx, vk in enumerate(modifier_s_new):
            key_dn_sc(vk)
            if modifier_interval:
                if vk_idx != vk_idx_max:
                    _time.sleep(modifier_interval)
        modifier_s_diff = _list_diff(modifier_s_old, modifier_s_new)
        for vk in modifier_s_diff:
            .
             Use `key_up_sc` because `key_up` does not work for DirectInput.
            key_up_sc(vk)
         ===== Release old modifiers =====
         ----- Press new non-modifiers -----
         Get max index of the new non-modifier list
        vk_idx_max = len(non_modifier_s_new) - 1
         For the new non-modifier list's each virtual key
        for vk_idx, vk in enumerate(non_modifier_s_new):
            .
             Use `key_dn_sc` because `key_dn` does not work for DirectInput.
            key_dn_sc(vk)
             If have key duration
            if key_duration:
                if vk_idx != vk_idx_max:
                     Sleep for key duration
                    _time.sleep(key_duration)
            key_up_sc(vk)
         ===== Press new non-modifiers =====
         ----- Release new non-modifiers -----
         For the new non-modifier list's each virtual key
        for vk in reversed(modifier_s_new):
            key_up_sc(vk)
         ===== Release new non-modifiers =====
         Set the previous group be the current group for next group
        previous_group = group
         If have key interval
        if key_interval:
             If is not the last group
            if group_idx != group_idx_max:
                 Sleep for key interval
                _time.sleep(key_interval)
     If need restore initial modifiers after sending the keys
    if restore_initial_modifiers:
         If the initial group is not the only group
        if previous_group is not initial_group:
             Get initial group's modifier list
            initial_modifier_s, _ = initial_group
             Get the max index
            vk_idx_max = len(initial_modifier_s) - 1
             For initial group's modifier list's each virtual key
            for vk_idx, vk in enumerate(initial_modifier_s):
                key_dn_sc(vk)
                if modifier_interval:
                    if vk_idx != vk_idx_max:
                        _time.sleep(modifier_interval)
def keys_stroke ( vks , vks_pressed = [ ] , key_duration = None , key_interval = None , modifier_interval = None , release_initial_keys = True , restore_initial_modifiers = True , ) : last_vk_is_modifier = True group_s = [ ] modifier_s = [ ] non_modifier_s = [ ] vk_idx = 0 vks_len = len ( vks ) while vk_idx < vks_len : vk = vks [ vk_idx ] vk_idx += 1 if not last_vk_is_modifier : group_s . append ( ( modifier_s , non_modifier_s ) ) modifier_s = [ ] non_modifier_s = [ ] if vk in _MODIFIER_VKS : modifier_s . append ( vk ) last_vk_is_modifier = True else : non_modifier_s . append ( vk ) last_vk_is_modifier = False if modifier_s or non_modifier_s : group_s . append ( ( modifier_s , non_modifier_s ) ) modifier_s = None non_modifier_s = None initial_group = ( tuple ( vk for vk in vks_pressed if vk in _MODIFIER_VKS ) , tuple ( vk for vk in vks_pressed if vk not in _MODIFIER_VKS ) , ) if release_initial_keys : for vk in initial_group [ 1 ] : key_up_sc ( vk ) previous_group = initial_group group_idx_max = len ( group_s ) - 1 for group_idx , group in enumerate ( group_s ) : modifier_s_old , _ = previous_group modifier_s_new , non_modifier_s_new = group vk_idx_max = len ( modifier_s_new ) - 1 for vk_idx , vk in enumerate ( modifier_s_new ) : key_dn_sc ( vk ) if modifier_interval : if vk_idx != vk_idx_max : _time . sleep ( modifier_interval ) modifier_s_diff = _list_diff ( modifier_s_old , modifier_s_new ) for vk in modifier_s_diff : key_up_sc ( vk ) vk_idx_max = len ( non_modifier_s_new ) - 1 for vk_idx , vk in enumerate ( non_modifier_s_new ) : key_dn_sc ( vk ) if key_duration : if vk_idx != vk_idx_max : _time . sleep ( key_duration ) key_up_sc ( vk ) for vk in reversed ( modifier_s_new ) : key_up_sc ( vk ) previous_group = group if key_interval : if group_idx != group_idx_max : _time . sleep ( key_interval ) if restore_initial_modifiers : if previous_group is not initial_group : initial_modifier_s , _ = initial_group vk_idx_max = len ( initial_modifier_s ) - 1 for vk_idx , vk in enumerate ( initial_modifier_s ) : key_dn_sc ( vk ) if modifier_interval : if vk_idx != vk_idx_max : _time . sleep ( modifier_interval )
Send keys, without being interfered by previously pressed modifier keys.
Send keys without being interfered by previously pressed modifier keys .
"""
    Send keys, without being interfered by previously pressed modifier keys.

    :param vks: Virtual keys to send.

    :param vks_pressed: Virtual keys that are currently pressed.

    :param key_duration: Duration between sending key-down and key-up events \
        for a non-modifier key.

    :param key_interval: Interval between sending events for two consecutive
        non-modifier keys.

    :param modifier_interval: Delay between sending key-down events for two \
        consecutive modifier keys.

    :param release_initial_keys: Whether send key-up events to release \
        non-modifier keys that were pressed before sending the keys. Notice
        initial modifier keys will always be released to avoid interference.

    :param restore_initial_modifiers: Whether send key-down events to press \
        modifier keys that were pressed before sending the keys.

    :return: None.
    """ # Whether last virtual key is modifier. # Initial value being True is required by code at 2NG2A. # Group list. # Each group is a tuple of (modifier_s, non_modifier_s). # Current group's modifier virtual key list # Current group's non-modifier virtual key list # Virtual key index # Virtual key list length # While have remaining virtual keys # Get a virtual key # Increment the virtual key index # 2NG2A # If last virtual key is not modifier, # it means the end of a group. # Add the group's modifiers and non-modifiers to the group list # Set the modifier virtual key list be empty for next group # Set the non-modifier virtual key list be empty for next group # If the virtual key is modifier # Add the virtual key to the modifier virtual key list # Set last virtual key is modifier be True # If the virtual key is not modifier # Add the virtual key to the non-modifier virtual key list # Set last virtual key is modifier be False # If the modifier or non-modifier virtual key list is not empty # Add the last group's modifiers and non-modifiers to the group list # Set the modifier virtual key list be None # Set the non-modifier virtual key list be None # Get initial group's modifier and non-modifier virtual key lists # If need release initial non-modifier keys # For initial group's each non-modifier virtual key # Send key-up event # Use the initial group as the initial previous group # Get max group index # For the group list's each group # Get previous group's modifiers # Get current group's modifiers and non-modifiers # ----- Press new modifiers ----- # Get max index of the new modifier list # For the new modifier list's each virtual key # Send key-down event # If have modifier interval # If the index is not the max index # Sleep for modifier interval # ===== Press new modifiers ===== # ----- Release old modifiers ----- # Get the two modifier lists' difference list. # The difference list contains the modifiers that should be released. # For the difference list's each virtual key # Send key-up event. # # Use `key_up_sc` because `key_up` does not work for DirectInput. # ===== Release old modifiers ===== # ----- Press new non-modifiers ----- # Get max index of the new non-modifier list # For the new non-modifier list's each virtual key # Send key-down event. # # Use `key_dn_sc` because `key_dn` does not work for DirectInput. # If have key duration # If the index is not the max index # Sleep for key duration # Send key-up event # ===== Press new non-modifiers ===== # ----- Release new non-modifiers ----- # For the new non-modifier list's each virtual key # Send key-up event # ===== Release new non-modifiers ===== # Set the previous group be the current group for next group # If have key interval # If is not the last group # Sleep for key interval # If need restore initial modifiers after sending the keys # If the initial group is not the only group # Get initial group's modifier list # Get the max index # For initial group's modifier list's each virtual key # Send key-down event # If have modifier interval # If the index is not the max index # Sleep for modifier interval
None
vks
Virtual keys to send.
Virtual keys to send .
vks_pressed
Virtual keys that are currently pressed.
Virtual keys that are currently pressed .
key_duration
Duration between sending key-down and key-up events \
for a non-modifier key.
Duration between sending key - down and key - up events \ for a non - modifier key .
key_interval
Interval between sending events for two consecutive
non-modifier keys.
Interval between sending events for two consecutive non - modifier keys .
modifier_interval
Delay between sending key-down events for two \
consecutive modifier keys.
Delay between sending key - down events for two \ consecutive modifier keys .
release_initial_keys
Whether send key-up events to release \
non-modifier keys that were pressed before sending the keys. Notice
initial modifier keys will always be released to avoid interference.
Whether send key - up events to release \ non - modifier keys that were pressed before sending the keys . Notice initial modifier keys will always be released to avoid interference .
restore_initial_modifiers
Whether send key-down events to press \
modifier keys that were pressed before sending the keys.
Whether send key - down events to press \ modifier keys that were pressed before sending the keys .