types.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #!/usr/bin/env python
  2. # License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
  3. from enum import Enum
  4. from functools import update_wrapper
  5. from typing import TYPE_CHECKING, Any, Callable, Dict, Generic, Iterator, Mapping, NamedTuple, Optional, Sequence, Tuple, TypedDict, TypeVar, Union
  6. if TYPE_CHECKING:
  7. from kitty.fast_data_types import SingleKey
  8. _T = TypeVar('_T')
  9. class SingleInstanceData(TypedDict):
  10. cmd: str
  11. args: Sequence[str]
  12. cmdline_args_for_open: Sequence[str]
  13. cwd: str
  14. session_data: str
  15. environ: Mapping[str, str]
  16. notify_on_os_window_death: Optional[str]
  17. class OverlayType(Enum):
  18. transient: str = 'transient'
  19. main: str = 'main'
  20. class ParsedShortcut(NamedTuple):
  21. mods: int
  22. key_name: str
  23. class Edges(NamedTuple):
  24. left: int = 0
  25. top: int = 0
  26. right: int = 0
  27. bottom: int = 0
  28. class FloatEdges(NamedTuple):
  29. left: float = 0
  30. top: float = 0
  31. right: float = 0
  32. bottom: float = 0
  33. class WindowGeometry(NamedTuple):
  34. left: int
  35. top: int
  36. right: int
  37. bottom: int
  38. xnum: int
  39. ynum: int
  40. spaces: Edges = Edges()
  41. class SignalInfo(NamedTuple):
  42. si_signo: int
  43. si_code: int
  44. si_pid: int
  45. si_uid: int
  46. si_addr: int
  47. si_status: int
  48. sival_int: int
  49. sival_ptr: int
  50. class LayerShellConfig(NamedTuple):
  51. type: int = 0
  52. edge: int = 0
  53. focus_policy: int = 0
  54. output_name: str = ''
  55. size_in_cells: int = 0
  56. def mod_to_names(mods: int, has_kitty_mod: bool = False, kitty_mod: int = 0) -> Iterator[str]:
  57. if has_kitty_mod:
  58. mods &= ~kitty_mod
  59. yield 'kitty_mod'
  60. for name, val in modmap().items():
  61. if mods & val:
  62. yield name
  63. def human_repr_of_single_key(self: 'SingleKey', kitty_mod: int) -> str:
  64. from .fast_data_types import glfw_get_key_name
  65. names = []
  66. names = list(mod_to_names(self.mods, self.defined_with_kitty_mod, kitty_mod))
  67. if self.key > 0:
  68. kname = (glfw_get_key_name(0, self.key) if self.is_native else glfw_get_key_name(self.key, 0)) or f'{self.key}'
  69. kname = {' ': 'space'}.get(kname, kname)
  70. names.append(kname)
  71. return '+'.join(names)
  72. class Shortcut(NamedTuple):
  73. keys: Tuple['SingleKey', ...]
  74. def human_repr(self, kitty_mod: int = 0) -> str:
  75. return ' > '.join(human_repr_of_single_key(k, kitty_mod) for k in self.keys)
  76. class MouseEvent(NamedTuple):
  77. button: int = 0
  78. mods: int = 0
  79. repeat_count: int = 1
  80. grabbed: bool = False
  81. def human_repr(self, kitty_mod: int = 0) -> str:
  82. from .options.utils import mouse_button_map, mouse_trigger_count_map
  83. def mouse_button_num_to_name(num: int) -> str:
  84. button_map = {v: k for k, v in mouse_button_map.items()}
  85. name = f'b{num+1}'
  86. return button_map.get(name, name)
  87. def mouse_trigger_count_to_name(count: int) -> str:
  88. trigger_count_map = {str(v): k for k, v in mouse_trigger_count_map.items()}
  89. k = str(count)
  90. return trigger_count_map.get(k, k)
  91. names = list(mod_to_names(self.mods)) + [mouse_button_num_to_name(self.button)]
  92. when = mouse_trigger_count_to_name(self.repeat_count)
  93. grabbed = 'grabbed' if self.grabbed else 'ungrabbed'
  94. return ' '.join(('+'.join(names), when, grabbed))
  95. class WindowSystemMouseEvent(NamedTuple):
  96. in_tab_bar: bool
  97. window_id: int
  98. action: int
  99. modifiers: int
  100. button: int
  101. currently_pressed_button: int
  102. x: float
  103. y: float
  104. ConvertibleToNumbers = Union[str, bytes, int, float]
  105. class AsyncResponse:
  106. pass
  107. if TYPE_CHECKING:
  108. class RunOnce(Generic[_T]):
  109. def __init__(self, func: Callable[[], _T]): ...
  110. def __call__(self) -> _T: ...
  111. def set_override(self, val: _T) -> None: ...
  112. def clear_override(self) -> None: ...
  113. def clear_cached(self) -> None: ...
  114. else:
  115. class RunOnce:
  116. def __init__(self, f):
  117. self._override = RunOnce
  118. self._cached_result = RunOnce
  119. update_wrapper(self, f)
  120. def __call__(self):
  121. if self._override is not RunOnce:
  122. return self._override
  123. if self._cached_result is RunOnce:
  124. self._cached_result = self.__wrapped__()
  125. return self._cached_result
  126. def clear_cached(self):
  127. self._cached_result = RunOnce
  128. def set_override(self, val):
  129. self._override = val
  130. def clear_override(self):
  131. self._override = RunOnce
  132. def run_once(f: Callable[[], _T]) -> 'RunOnce[_T]':
  133. return RunOnce(f)
  134. @run_once
  135. def modmap() -> Dict[str, int]:
  136. from .constants import is_macos
  137. from .fast_data_types import (
  138. GLFW_MOD_ALT,
  139. GLFW_MOD_CAPS_LOCK,
  140. GLFW_MOD_CONTROL,
  141. GLFW_MOD_HYPER,
  142. GLFW_MOD_META,
  143. GLFW_MOD_NUM_LOCK,
  144. GLFW_MOD_SHIFT,
  145. GLFW_MOD_SUPER,
  146. )
  147. return {'ctrl': GLFW_MOD_CONTROL, 'shift': GLFW_MOD_SHIFT, ('opt' if is_macos else 'alt'): GLFW_MOD_ALT,
  148. ('cmd' if is_macos else 'super'): GLFW_MOD_SUPER, 'hyper': GLFW_MOD_HYPER, 'meta': GLFW_MOD_META,
  149. 'caps_lock': GLFW_MOD_CAPS_LOCK, 'num_lock': GLFW_MOD_NUM_LOCK}
  150. if TYPE_CHECKING:
  151. from typing import Literal
  152. ActionGroup = Literal['cp', 'sc', 'win', 'tab', 'mouse', 'mk', 'lay', 'misc', 'debug']
  153. else:
  154. ActionGroup = str
  155. class ActionSpec(NamedTuple):
  156. group: str
  157. doc: str
  158. def ac(group: ActionGroup, doc: str) -> Callable[[_T], _T]:
  159. def w(f: _T) -> _T:
  160. setattr(f, 'action_spec', ActionSpec(group, doc))
  161. return f
  162. return w
  163. DecoratedFunc = TypeVar('DecoratedFunc', bound=Callable[..., Any])