Skip to content

Instantly share code, notes, and snippets.

@Versatilus
Created September 16, 2015 01:09
Show Gist options
  • Save Versatilus/bec104228952b97e54fe to your computer and use it in GitHub Desktop.
Save Versatilus/bec104228952b97e54fe to your computer and use it in GitHub Desktop.
Custom alterations to Typeable class in Dragonfly's keyboard.py
#
# 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)
#---------------------------------------------------------------------------
# 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=0.04):
""" Returns events for pressing this key down. """
events = [(m, True, timeout * 2) for m in self._modifiers]
events.append((self._code, True, timeout))
return events
def off_events(self, timeout=0.04):
""" Returns events for releasing this key. """
events = [(m, False, timeout * 2) for m in self._modifiers]
events.append((self._code, False, timeout))
events.reverse()
return events
def events(self, timeout=0.08):
""" Returns events for pressing and then releasing this key. """
events = [(self._code, True, timeout/2), (self._code, False, timeout/2)]
for m in self._modifiers[-1::-1]:
events.insert(0, (m, True, timeout))
events.append((m, False , timeout))
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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment