示例#1
0
class Keystroke_Watcher:
    def __init__(self, master, sticky=False):
        self.logger = logging.getLogger(master.logger.name +
                                        '.Keystroke_Watcher')
        self.hm = HookManager()
        self.hm.KeyDown = self.on_key_down
        self.hm.KeyUp = self.on_key_up
        self.function_map = {}
        self.keys_held = set()
        self.sticky = sticky
        self.hm.HookKeyboard()

    def get_key_combo_code(self):
        return '+'.join(
            [HookConstants.IDToName(key) for key in self.keys_held])

    def register_function(self, key_combo, function):
        self.function_map[key_combo.lower()] = function
        self.logger.info("Registered function <{}> to keycombo <{}>.".format(
            function.__name__, key_combo.lower()))

    def unregister_function(self, key_combo):
        self.logger.info("Unregistered function <{}> at keycombo <{}>".format(
            self.function_map[key_combo.lower()].__name__, key_combo.lower()))
        del self.function_map[key_combo.lower()]

    def on_key_down(self, event):
        try:
            self.keys_held.add(event.KeyID)
        finally:
            return True

    def on_key_up(self, event):
        keycombo = self.get_key_combo_code().lower()
        try:
            if keycombo in self.function_map.keys():
                self.logger.info(
                    "Shortcut <{}> pressed. Calling function <{}>.".format(
                        keycombo, self.function_map[keycombo].__name__))
                self.function_map[keycombo]()
        finally:
            if not self.sticky:
                self.keys_held.remove(event.KeyID)
            return True

    def shutdown(self):
        self.hm.UnhookKeyboard()

    def restart(self):
        self.keys_held = set()
        self.hm.HookKeyboard()
示例#2
0
class KeybindManager:
    """ Interface with Mouse/Keyboard and register functions to keyboard shortcuts. """

    def __init__(self, master, sticky=False):
        self.logger = logging.getLogger(master.logger.name + '.Keystroke_Watcher')
        self.hook_manager = HookManager()
        self.hook_manager.KeyDown = self._on_key_down
        self.hook_manager.KeyUp = self._on_key_up
        self.function_map = {}
        self.keys_held = set()
        self.sticky = sticky
        self.hook_manager.HookKeyboard()

    def get_key_combo_code(self):
        """ Converts the keys currently being held into a string representing the combination """
        return '+'.join([HookConstants.IDToName(key) for key in self.keys_held])

    def register_function(self, key_combo, function):
        """ Register function callback to key_combo """
        self.function_map[key_combo.lower()] = function
        self.logger.info(
            "Registered function <%s> to keycombo <%s>.", function.__name__, key_combo.lower())

    def unregister_function(self, key_combo):
        """ Stop tracking function at key_combo """
        self.logger.info(
            "Unregistered function <%s> at keycombo <%s>", self.function_map[key_combo.lower()].__name__,
            key_combo.lower())
        del self.function_map[key_combo.lower()]

    def _on_key_down(self, event):
        """ Simply adds the key to keys held. """
        try:
            self.keys_held.add(event.KeyID)
        except Exception as exc:
            # Log error but don't do anything; PyHook is prone to throw some exceptions with no consequences
            self.logger.error("Error in _on_key_down, %s", exc)
        return True

    def _on_key_up(self, event):
        """ If a function for the given key_combo is found, call it """
        key_combo = self.get_key_combo_code().lower()
        try:
            if key_combo in self.function_map.keys():
                self.logger.info(
                    "Shortcut <%s> pressed. Calling function <%s>.", key_combo,
                    self.function_map[key_combo].__name__)
                self.function_map[key_combo]()
        finally:
            if not self.sticky and event.KeyID in self.keys_held:
                self.keys_held.remove(event.KeyID)
        return True

    def shutdown(self):
        """ Stop following keyboard events. """
        self.hook_manager.UnhookKeyboard()

    def restart(self):
        """ Clear keys held and rehook keyboard. """
        self.keys_held = set()
        self.hook_manager.HookKeyboard()
示例#3
0
class EventManager(object):
    """
    Event manager that runs event loop and calls event handlers.
    """

    def __init__(self):
        """
        Constructor.

        :return: None.
        """
        # Create hook manager
        self._hook_manager = HookManager()

        # Add attributes `mouse_hook` and `keyboard_hook`.
        # Without the two attributes, the hook manager's method `__del__`
        # will raise AttributeError if its methods `HookKeyboard` and
        # `HookMouse` have not been called.
        self._hook_manager.mouse_hook = False

        self._hook_manager.keyboard_hook = False

    def start_event_loop(self):
        """
        Start event loop.

        This method will not return until the event loop is stopped by \
        calling :paramref:`stop_event_loop`.

        :return: None.
        """
        # Start hooking key events
        self._hook_manager.HookKeyboard()

        # Start hooking mouse events
        self._hook_manager.HookMouse()

        # Create MSG structure
        msg = MSG()

        # Run event loop
        GetMessageW(byref(msg), 0, 0, 0)

        # Stop hooking key events
        self._hook_manager.UnhookKeyboard()

        # Stop hooking mouse events
        self._hook_manager.UnhookMouse()

    def stop_event_loop(self):
        """
        Stop event loop.

        :return: None.
        """
        # Post a WM_QUIT message to this thread's message queue
        PostQuitMessage(0)

    # Map event handler type to handler attribute name
    _EVENT_HANDLER_TYPE_TO_ATTR_NAME = {
        'KeyDown': 'KeyDown',
        'KeyUp': 'KeyUp',
        'MouseDown': 'MouseAllButtonsDown',
        'MouseUp': 'MouseAllButtonsUp',
        'MouseMove': 'MouseMove',
        'MouseWheel': 'MouseWheel',
    }

    def add_handler(self, handler_type, handler):
        """
        Add event handler.

        :param handler_type: Event handler type.

        Allowed values:
            - 'KeyDown'
            - 'KeyUp'
            - 'MouseDown'
            - 'MouseUp'
            - 'MouseMove'
            - 'MouseWheel'

        :param handler: Event handler.

        :return: None.
        """
        # Get handler attribute name
        attr_name = self._EVENT_HANDLER_TYPE_TO_ATTR_NAME.get(
            handler_type, None
        )

        # If handler attribute name is not found,
        # it means given handler type is not valid.
        if attr_name is None:
            # Get error message
            msg = 'Error: Invalid handler type: {0}'.format(
                repr(handler_type)
            )

            # Raise error
            raise ValueError(msg)

        # If handler attribute name is found.

        # Set the handler attribute on the hook manager
        setattr(self._hook_manager, attr_name, handler)

    def remove_handlers(self):
        """
        Remove all event handlers.

        :return: None.
        """
        # Set handler attributes on the hook manager be None
        self._hook_manager.KeyDown = None

        self._hook_manager.KeyUp = None

        self._hook_manager.MouseAllButtonsDown = None

        self._hook_manager.MouseAllButtonsUp = None

        self._hook_manager.MouseMove = None

        self._hook_manager.MouseWheel = None