def test_numlock(self): before = is_numlock_on() set_numlock(not before) # should change self.assertEqual(not before, is_numlock_on()) @ensure_numlock def wrapped_1(): set_numlock(not is_numlock_on()) @ensure_numlock def wrapped_2(): pass # should not change wrapped_1() self.assertEqual(not before, is_numlock_on()) wrapped_2() self.assertEqual(not before, is_numlock_on()) # toggle one more time to restore the previous configuration set_numlock(before) self.assertEqual(before, is_numlock_on())
def wrapped_1(): set_numlock(not is_numlock_on())
def run(self): """The injection worker that keeps injecting until terminated. Stuff is non-blocking by using asyncio in order to do multiple things somewhat concurrently. Use this function as starting point in a process. It creates the loops needed to read and map events and keeps running them. """ logger.info('Starting injecting the mapping for "%s"', self.group.key) # create a new event loop, because somehow running an infinite loop # that sleeps on iterations (event_producer) in one process causes # another injection process to screw up reading from the grabbed # device. loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) # create this within the process after the event loop creation, # so that the macros use the correct loop self.context = Context(self.mapping) # grab devices as early as possible. If events appear that won't get # released anymore before the grab they appear to be held down # forever sources = self._grab_devices() self._event_producer = EventProducer(self.context) numlock_state = is_numlock_on() coroutines = [] # where mapped events go to. # See the Context docstring on why this is needed. self.context.uinput = evdev.UInput( name=self.get_udev_name(self.group.key, 'mapped'), phys=DEV_NAME, events=self._construct_capabilities(GAMEPAD in self.group.types)) for source in sources: # certain capabilities can have side effects apparently. with an # EV_ABS capability, EV_REL won't move the mouse pointer anymore. # so don't merge all InputDevices into one UInput device. gamepad = classify(source) == GAMEPAD forward_to = evdev.UInput(name=self.get_udev_name( source.name, 'forwarded'), phys=DEV_NAME, events=self._copy_capabilities(source)) # actual reading of events coroutines.append(self._event_consumer(source, forward_to)) # The event source of the current iteration will deliver events # that are needed for this. It is that one that will be mapped # to a mouse-like devnode. if gamepad and self.context.joystick_as_mouse(): self._event_producer.set_abs_range_from(source) if len(coroutines) == 0: logger.error('Did not grab any device') self._msg_pipe[0].send(NO_GRAB) return coroutines.append(self._msg_listener()) # run besides this stuff coroutines.append(self._event_producer.run()) # set the numlock state to what it was before injecting, because # grabbing devices screws this up set_numlock(numlock_state) self._msg_pipe[0].send(OK) try: loop.run_until_complete(asyncio.gather(*coroutines)) except RuntimeError: # stopped event loop most likely pass except OSError as error: logger.error(str(error)) if len(coroutines) > 0: # expected when stop_injecting is called, # during normal operation as well as tests this point is not # reached otherwise. logger.debug('asyncio coroutines ended') for source in sources: # ungrab at the end to make the next injection process not fail # its grabs source.ungrab()