Created
September 16, 2015 01:09
-
-
Save Versatilus/bec104228952b97e54fe to your computer and use it in GitHub Desktop.
Custom alterations to Typeable class in Dragonfly's keyboard.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# 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