try: import Xlib.X import Xlib.protocol.event except ImportError: pass class TargetEngine: Primary = -1 All = -3 class EngineAction: def __init__(self, target_engine_index): self._target_engine_index = target_engine_index def execute_on_window(self, extended_controls, xkeyevent, engine_window): raise Exception('abstract method') def execute(self, extended_controls, xkeyevent): if self._target_engine_index == TargetEngine.Primary: target_windows = [extended_controls.primary_engine_window] elif self._target_engine_index == TargetEngine.All: target_windows = extended_controls.engine_windows else: target_windows = extended_controls.engine_windows_by_target_index.get( self._target_engine_index, [], ) for target_window in target_windows: self.execute_on_window(extended_controls, xkeyevent, target_window) class SelectGagAction(EngineAction): def __init__(self, target_engine_index, factor_x, factor_y): super().__init__( target_engine_index=target_engine_index, ) self._button = Xlib.X.Button1 self._factor_x = factor_x self._factor_y = factor_y def execute_on_window(self, extended_controls, xkeyevent, engine_window): engine_geometry = engine_window.get_geometry() smaller_dimension = min(engine_geometry.width, engine_geometry.height) attr = dict( window=engine_window, detail=self._button, state=xkeyevent.state, event_x=int(engine_geometry.width / 2 + smaller_dimension * self._factor_x), event_y=int(engine_geometry.height / 2 + smaller_dimension * self._factor_y), # apparently root_x & root_y do not need to correspond with event_x/y. # attributes are still required to be set. root_x=0, # xkeyevent.root_x, root_y=0, # xkeyevent.root_y, child=xkeyevent.child, root=xkeyevent.root, time=xkeyevent.time, # X.CurrentTime same_screen=xkeyevent.same_screen, ) if isinstance(xkeyevent, Xlib.protocol.event.KeyPress): e = Xlib.protocol.event.ButtonPress(**attr) else: e = Xlib.protocol.event.ButtonRelease(**attr) engine_window.send_event(e) class RewriteKeyEventAction(EngineAction): def __init__(self, target_engine_index, keysym=None): super().__init__( target_engine_index=target_engine_index, ) self._keysym = keysym def execute_on_window(self, extended_controls, xkeyevent, engine_window): engine_window.send_event(type(xkeyevent)( window=engine_window, detail=extended_controls.xdisplay.keysym_to_keycode(self._keysym) if self._keysym else xkeyevent.detail, state=xkeyevent.state, root_x=xkeyevent.root_x, root_y=xkeyevent.root_y, event_x=xkeyevent.event_x, event_y=xkeyevent.event_y, child=xkeyevent.child, root=xkeyevent.root, time=xkeyevent.time, # X.CurrentTime same_screen=xkeyevent.same_screen, )) class ForwardKeyEventAction(RewriteKeyEventAction): def __init__(self): super().__init__( keysym=None, target_engine_index=TargetEngine.Primary, ) class ToggleExtendedControlsAction: def execute(self, extended_controls, xkeyevent): if isinstance(xkeyevent, Xlib.protocol.event.KeyPress): extended_controls.toggle()