Skip to content

Instantly share code, notes, and snippets.

@Versatilus
Created September 27, 2019 07:56
Show Gist options
  • Save Versatilus/ebbd8ccc00be35b02f2200255edf2d70 to your computer and use it in GitHub Desktop.
Save Versatilus/ebbd8ccc00be35b02f2200255edf2d70 to your computer and use it in GitHub Desktop.
from __future__ import print_function, unicode_literals
from ctypes import windll
from dragonfly import (ActionBase, Choice, Grammar, IntegerRef, Key,
MappingRule, Mouse, Pause, Repeat)
from dragonfly.actions.keyboard import Keyboard, KeySymbols
KEYBOARD = Keyboard()
GET_ASYNC_KEY_STATE = windll.user32.GetAsyncKeyState
class ModifierAction(ActionBase):
"""
Wrap arbitrary actions within keyboard presses.
Currently Windows-only.
"""
def __init__(self, action, modifiers=None):
"""
Set `Action` instance to execute and prime modifiers list.
`modifiers` must be a sequence of valid Windows keyboard codes.
"""
super(ModifierAction, self).__init__()
self.action = action
if not (isinstance(modifiers, (list, tuple)) or modifiers is None):
raise TypeError("`modifiers` must be a list, tuple, or `None`.")
self._modifiers = tuple(modifiers) if modifiers else []
def _execute(self, data=None):
modifiers = list(self._modifiers)
for key, value in data.items():
if "modifier_" in key:
modifiers.append(value)
# Only activate modifier keys which aren't currently being held down,
# the assumption being the keys are being held down for a reason.
modifiers_down = [(modifier, True, .1)
for modifier in modifiers
if GET_ASYNC_KEY_STATE(modifier) & 0x8000 == 0]
KEYBOARD.send_keyboard_events(modifiers_down)
self.action.execute(data)
# Similar to before, only release keys that are being held and
# we are responsible for pressing.
modifiers_up = [(modifier, False, .1)
for (modifier, i, j) in modifiers_down
if (GET_ASYNC_KEY_STATE(modifier) & 0x8000) != 0]
KEYBOARD.send_keyboard_events(modifiers_up)
GRAMMAR = Grammar("Modifier Action example")
SHIFT_KEY = KeySymbols.SHIFT
SUPER_KEY = KeySymbols.LSUPER
ALT_KEY = KeySymbols.ALT
CONTROL_KEY = KeySymbols.CONTROL
MODIFIERS = {
"[left] alt": ALT_KEY,
"[left] shift": SHIFT_KEY,
"[left] control": CONTROL_KEY,
"[left] (windows|super)": SUPER_KEY,
}
class ExampleRule(MappingRule):
mapping = {
"[<modifier_1>][<modifier_2>][<modifier_3>] extended <fkey>":
ModifierAction(Key("f%(fkey)d")),
"after [this] tab [<n>]":
ModifierAction(Key("tab/10:%(n)d"), modifiers=[CONTROL_KEY]),
"before [this] tab [<n>]":
ModifierAction(
Key("tab/10:%(n)d"), modifiers=[CONTROL_KEY, SHIFT_KEY]),
"[<modifier_1>][<modifier_2>][<modifier_3>] punch [<n>]":
ModifierAction(
(Mouse("left:down") + Pause("10") + Mouse("left:up") +
Pause("10")) * Repeat(extra="n")),
}
extras = [
IntegerRef("n", 1, 10),
IntegerRef("fkey", 1, 25),
Choice("modifier_1", MODIFIERS),
Choice("modifier_2", MODIFIERS),
Choice("modifier_3", MODIFIERS),
]
defaults = {"n": 1}
GRAMMAR.add_rule(ExampleRule())
GRAMMAR.load()
def unload():
global GRAMMAR
if GRAMMAR:
GRAMMAR.unload()
GRAMMAR = None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment