Skip to content

Instantly share code, notes, and snippets.

@chilimangoes
Created September 17, 2015 22:38

Revisions

  1. chilimangoes created this gist Sep 17, 2015.
    27 changes: 27 additions & 0 deletions configcustom.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,27 @@
    from dragonfly import *
    from dragonfly.actions import keyboard
    from caster.lib import navigation, context, utilities
    from caster.lib.dfplus.additions import SelectiveAction
    from caster.lib.dfplus.state.actions import ContextSeeker, AsynchronousAction, RegisteredAction
    from caster.lib.dfplus.state.short import L, S, R

    # ...

    def set_keyboard_timeout(timeout):
    print(timeout)
    keyboard.default_timeout = timeout

    # ...

    cmd.map = {

    # ...

    "set keyboard long": R(Function(set_keyboard_timeout, timeout=0.20), rspec="set keyboard long", rdescript="Set Keyboard Long"),
    "set keyboard short": R(Function(set_keyboard_timeout, timeout=0.01), rspec="set keyboard short", rdescript="Set Keyboard Short"),

    # ...

    }

    # ...
    160 changes: 160 additions & 0 deletions keyboard.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,160 @@
    #
    # This file is part of Dragonfly.
    # (c) Copyright 2007, 2008 by Christo Butcher
    # Licensed under the LGPL.
    #
    # Dragonfly is free software: you can redistribute it and/or modify it
    # under the terms of the GNU Lesser General Public License as published
    # by the Free Software Foundation, either version 3 of the License, or
    # (at your option) any later version.
    #
    # Dragonfly is distributed in the hope that it will be useful, but
    # WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    # Lesser General Public License for more details.
    #
    # You should have received a copy of the GNU Lesser General Public
    # License along with Dragonfly. If not, see
    # <http://www.gnu.org/licenses/>.
    #

    """
    This file implements a Win32 keyboard interface using sendinput.
    """


    import time
    import win32con
    from ctypes import windll, c_char, c_wchar
    from dragonfly.actions.sendinput import (KeyboardInput, make_input_array,
    send_input_array)


    # Default timeout for key presses. Lower values increases typing
    # speed for dictated text and keys. Higher values may be needed in
    # some situations, for example, when sending keystrokes to a remote
    # desktop over a VPN.
    default_timeout = 0.04

    #---------------------------------------------------------------------------
    # Typeable class.

    class Typeable(object):

    __slots__ = ("_code", "_modifiers", "_name")

    def __init__(self, code, modifiers=(), name=None):
    self._code = code
    self._modifiers = modifiers
    self._name = name

    def __str__(self):
    return "%s(%s)" % (self.__class__.__name__, self._name) + repr(self.events())

    def on_events(self, timeout=None):
    """ Returns events for pressing this key down. """
    global default_timeout
    timeout = default_timeout if timeout == None else timeout
    events = [(m, True, timeout * 2) for m in self._modifiers]
    events.append((self._code, True, timeout))
    return events

    def off_events(self, timeout=None):
    """ Returns events for releasing this key. """
    global default_timeout
    timeout = default_timeout if timeout == None else timeout
    events = [(m, False, timeout * 2) for m in self._modifiers]
    events.append((self._code, False, timeout))
    events.reverse()
    return events

    def events(self, timeout=None):
    """ Returns events for pressing and then releasing this key. """
    global default_timeout
    timeout = default_timeout if timeout == None else timeout
    events = [(self._code, True, timeout), (self._code, False, timeout)]
    for m in self._modifiers[-1::-1]:
    events.insert(0, (m, True, timeout * 2))
    events.append((m, False , timeout * 2))
    return events


    #---------------------------------------------------------------------------
    # Keyboard access class.

    class Keyboard(object):

    shift_code = win32con.VK_SHIFT
    ctrl_code = win32con.VK_CONTROL
    alt_code = win32con.VK_MENU

    @classmethod
    def send_keyboard_events(cls, events):
    """
    Send a sequence of keyboard events.
    Positional arguments:
    events -- a sequence of 3-tuples of the form
    (keycode, down, timeout), where
    keycode (int): virtual key code.
    down (boolean): True means the key will be pressed down,
    False means the key will be released.
    timeout (int): number of seconds to sleep after
    the keyboard event.
    """
    items = []
    for keycode, down, timeout in events:
    input = KeyboardInput(keycode, down)
    items.append(input)
    if timeout:
    array = make_input_array(items)
    items = []
    send_input_array(array)
    time.sleep(timeout)
    if items:
    array = make_input_array(items)
    send_input_array(array)
    if timeout: time.sleep(timeout)

    @classmethod
    def xget_virtual_keycode(cls, char):
    if isinstance(char, str):
    code = windll.user32.VkKeyScanA(c_char(char))
    else:
    code = windll.user32.VkKeyScanW(c_wchar(char))
    if code == -1:
    raise ValueError("Unknown char: %r" % char)

    # Construct a list of the virtual key code and modifiers.
    codes = [code & 0x00ff]
    if code & 0x0100: codes.append(cls.shift_code)
    elif code & 0x0200: codes.append(cls.ctrl_code)
    elif code & 0x0400: codes.append(cls.alt_code)
    return codes

    @classmethod
    def get_keycode_and_modifiers(cls, char):
    if isinstance(char, str):
    code = windll.user32.VkKeyScanA(c_char(char))
    else:
    code = windll.user32.VkKeyScanW(c_wchar(char))
    if code == -1:
    raise ValueError("Unknown char: %r" % char)

    # Construct a list of the virtual key code and modifiers.
    modifiers = []
    if code & 0x0100: modifiers.append(cls.shift_code)
    elif code & 0x0200: modifiers.append(cls.ctrl_code)
    elif code & 0x0400: modifiers.append(cls.alt_code)
    code &= 0x00ff
    return code, modifiers

    @classmethod
    def get_typeable(cls, char):
    code, modifiers = cls.get_keycode_and_modifiers(char)
    return Typeable(code, modifiers)


    keyboard = Keyboard()