You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
2.7 KiB

2 years ago
# coding=utf-8
# pynput
# Copyright (C) 2015-2022 Moses Palmér
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
"""
Utility functions and classes for the *uinput* backend.
"""
# pylint: disable=R0903
# We implement stubs
import evdev
# Check that we have permissions to continue
def _check():
# TODO: Implement!
pass
_check()
del _check
class ListenerMixin(object):
"""A mixin for *uinput* event listeners.
Subclasses should set a value for :attr:`_EVENTS` and implement
:meth:`_handle`.
"""
#: The events for which to listen
_EVENTS = tuple()
def __init__(self, *args, **kwargs):
super(ListenerMixin, self).__init__(*args, **kwargs)
self._dev = self._device(self._options.get(
'device_paths',
evdev.list_devices()))
if self.suppress:
self._dev.grab()
def _run(self):
for event in self._dev.read_loop():
if event.type in self._EVENTS:
self._handle(event)
def _stop_platform(self):
self._dev.close()
def _device(self, paths):
"""Attempts to load a readable keyboard device.
:param paths: A list of paths.
:return: a compatible device
"""
dev, count = None, 0
for path in paths:
# Open the device
try:
next_dev = evdev.InputDevice(path)
except OSError:
continue
# Does this device provide more handled event codes?
capabilities = next_dev.capabilities()
next_count = sum(
len(codes)
for event, codes in capabilities.items()
if event in self._EVENTS)
if next_count > count:
dev = next_dev
count = next_count
else:
next_dev.close()
if dev is None:
raise OSError('no keyboard device available')
else:
return dev
def _handle(self, event):
"""Handles a single event.
This method should call one of the registered event callbacks.
:param event: The event.
"""
raise NotImplementedError()