actions.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. try:
  2. import Xlib.X
  3. import Xlib.protocol.event
  4. except ImportError:
  5. pass
  6. class TargetEngine:
  7. Primary = -1
  8. All = -3
  9. class EngineAction:
  10. def __init__(self, target_engine_index):
  11. self._target_engine_index = target_engine_index
  12. def execute_on_window(self, extended_controls, xkeyevent, engine_window):
  13. raise Exception("abstract method")
  14. def execute(self, extended_controls, xkeyevent):
  15. if self._target_engine_index == TargetEngine.Primary:
  16. target_windows = [extended_controls.primary_engine_window]
  17. elif self._target_engine_index == TargetEngine.All:
  18. target_windows = extended_controls.engine_windows
  19. else:
  20. target_windows = extended_controls.engine_windows_by_target_index.get(
  21. self._target_engine_index, [],
  22. )
  23. for target_window in target_windows:
  24. self.execute_on_window(extended_controls, xkeyevent, target_window)
  25. class CenterClickAction(EngineAction):
  26. def __init__(self, target_engine_index, factor_x, factor_y):
  27. super().__init__(target_engine_index=target_engine_index,)
  28. self._button = Xlib.X.Button1
  29. self._factor_x = factor_x
  30. self._factor_y = factor_y
  31. def execute_on_window(self, extended_controls, xkeyevent, engine_window):
  32. engine_geometry = engine_window.get_geometry()
  33. smaller_dimension = min(engine_geometry.width, engine_geometry.height)
  34. attr = dict(
  35. window=engine_window,
  36. detail=self._button,
  37. state=xkeyevent.state,
  38. event_x=int(engine_geometry.width / 2 + smaller_dimension * self._factor_x),
  39. event_y=int(
  40. engine_geometry.height / 2 + smaller_dimension * self._factor_y
  41. ),
  42. # apparently root_x & root_y do not need to correspond with event_x/y.
  43. # attributes are still required to be set.
  44. root_x=0, # xkeyevent.root_x,
  45. root_y=0, # xkeyevent.root_y,
  46. child=xkeyevent.child,
  47. root=xkeyevent.root,
  48. time=xkeyevent.time, # X.CurrentTime
  49. same_screen=xkeyevent.same_screen,
  50. )
  51. if isinstance(xkeyevent, Xlib.protocol.event.KeyPress):
  52. e = Xlib.protocol.event.ButtonPress(**attr)
  53. else:
  54. e = Xlib.protocol.event.ButtonRelease(**attr)
  55. engine_window.send_event(e)
  56. class SelectGagAction(CenterClickAction):
  57. X_OFFSET = -0.286
  58. X_FACTOR = 0.081
  59. def __init__(self, target_engine_index, column_index, factor_y):
  60. super().__init__(
  61. target_engine_index=target_engine_index,
  62. factor_x=self.X_OFFSET + self.X_FACTOR * column_index,
  63. factor_y=factor_y,
  64. )
  65. class RewriteKeyEventAction(EngineAction):
  66. def __init__(self, target_engine_index, keysym=None):
  67. super().__init__(target_engine_index=target_engine_index,)
  68. self._keysym = keysym
  69. def execute_on_window(self, extended_controls, xkeyevent, engine_window):
  70. engine_window.send_event(
  71. type(xkeyevent)(
  72. window=engine_window,
  73. detail=extended_controls.xdisplay.keysym_to_keycode(self._keysym)
  74. if self._keysym
  75. else xkeyevent.detail,
  76. state=xkeyevent.state,
  77. root_x=xkeyevent.root_x,
  78. root_y=xkeyevent.root_y,
  79. event_x=xkeyevent.event_x,
  80. event_y=xkeyevent.event_y,
  81. child=xkeyevent.child,
  82. root=xkeyevent.root,
  83. time=xkeyevent.time, # X.CurrentTime
  84. same_screen=xkeyevent.same_screen,
  85. )
  86. )
  87. class ForwardKeyEventAction(RewriteKeyEventAction):
  88. def __init__(self):
  89. super().__init__(
  90. keysym=None, target_engine_index=TargetEngine.Primary,
  91. )
  92. class ToggleExtendedControlsAction:
  93. def execute(self, extended_controls, xkeyevent):
  94. if isinstance(xkeyevent, Xlib.protocol.event.KeyPress):
  95. extended_controls.toggle()