plover 5.0.0.dev3__tar.gz → 5.0.0rc1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. {plover-5.0.0.dev3 → plover-5.0.0rc1}/NEWS.md +19 -0
  2. {plover-5.0.0.dev3/plover.egg-info → plover-5.0.0rc1}/PKG-INFO +1 -1
  3. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/ci.md +1 -6
  4. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/conf.py +1 -1
  5. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/__init__.py +1 -1
  6. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/linux/keyboardcontrol_uinput.py +137 -37
  7. {plover-5.0.0.dev3 → plover-5.0.0rc1/plover.egg-info}/PKG-INFO +1 -1
  8. {plover-5.0.0.dev3 → plover-5.0.0rc1}/CONTRIBUTING.md +0 -0
  9. {plover-5.0.0.dev3 → plover-5.0.0rc1}/LICENSE.txt +0 -0
  10. {plover-5.0.0.dev3 → plover-5.0.0rc1}/MANIFEST.in +0 -0
  11. {plover-5.0.0.dev3 → plover-5.0.0rc1}/README.md +0 -0
  12. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/SCOWL_README.txt +0 -0
  13. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/_static/board-layout.png +0 -0
  14. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/_static/custom.css +0 -0
  15. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/_static/de-speech.png +0 -0
  16. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/_static/dolores.svg +0 -0
  17. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/_static/engine-flow.png +0 -0
  18. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/_static/favicon.ico +0 -0
  19. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/_static/jp-speech.png +0 -0
  20. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/_static/keys-layout.png +0 -0
  21. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/_static/uncomfortable.png +0 -0
  22. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/_templates/breadcrumbs.html +0 -0
  23. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/_templates/layout.html +0 -0
  24. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/add_translation.md +0 -0
  25. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/config.md +0 -0
  26. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/dictionary.md +0 -0
  27. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/dictionary_lib.md +0 -0
  28. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/engine.md +0 -0
  29. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/exception.md +0 -0
  30. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/formatting.md +0 -0
  31. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/i18n.md +0 -0
  32. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/key_combo.md +0 -0
  33. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/log.md +0 -0
  34. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/machine.md +0 -0
  35. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/machine_keyboard_capture.md +0 -0
  36. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/machine_keymap.md +0 -0
  37. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/misc.md +0 -0
  38. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/orthography.md +0 -0
  39. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/oslayer.md +0 -0
  40. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/oslayer_config.md +0 -0
  41. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/oslayer_controller.md +0 -0
  42. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/oslayer_i18n.md +0 -0
  43. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/oslayer_keyboardcontrol.md +0 -0
  44. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/oslayer_log.md +0 -0
  45. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/oslayer_wmctrl.md +0 -0
  46. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/output.md +0 -0
  47. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/plover.md +0 -0
  48. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/plover_stroke.md +0 -0
  49. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/qt.md +0 -0
  50. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/registry.md +0 -0
  51. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/resource.md +0 -0
  52. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/steno.md +0 -0
  53. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/steno_dictionary.md +0 -0
  54. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/suggestions.md +0 -0
  55. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/system.md +0 -0
  56. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api/translation.md +0 -0
  57. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/api_reference.md +0 -0
  58. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/basic_usage.md +0 -0
  59. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/cli_reference.md +0 -0
  60. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/configuration.md +0 -0
  61. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/contributing.md +0 -0
  62. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/design.md +0 -0
  63. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/developer_guide.md +0 -0
  64. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/dict_editor.md +0 -0
  65. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/dict_formats.md +0 -0
  66. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/dictionaries.md +0 -0
  67. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/hardware_communication.md +0 -0
  68. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/hardware_setup.md +0 -0
  69. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/i18n.md +0 -0
  70. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/index.md +0 -0
  71. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/installation.md +0 -0
  72. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/internals.md +0 -0
  73. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/platform_layer.md +0 -0
  74. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/plugin-dev/commands.md +0 -0
  75. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/plugin-dev/dictionaries.md +0 -0
  76. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/plugin-dev/extensions.md +0 -0
  77. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/plugin-dev/gui_tools.md +0 -0
  78. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/plugin-dev/machines.md +0 -0
  79. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/plugin-dev/macros.md +0 -0
  80. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/plugin-dev/metas.md +0 -0
  81. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/plugin-dev/publishing.md +0 -0
  82. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/plugin-dev/setup.md +0 -0
  83. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/plugin-dev/systems.md +0 -0
  84. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/plugin_dev.md +0 -0
  85. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/plugins.md +0 -0
  86. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/releases.md +0 -0
  87. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/requirements.txt +0 -0
  88. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/system-dev/board-layout.md +0 -0
  89. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/system-dev/key-arrangement.md +0 -0
  90. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/system-dev/layout-test.md +0 -0
  91. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/system-dev/steno-system.md +0 -0
  92. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/system-dev/system.md +0 -0
  93. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/system_dev.md +0 -0
  94. {plover-5.0.0.dev3 → plover-5.0.0rc1}/doc/translation_language.md +0 -0
  95. {plover-5.0.0.dev3 → plover-5.0.0rc1}/linux/README.md +0 -0
  96. {plover-5.0.0.dev3 → plover-5.0.0rc1}/linux/appimage/Dockerfile +0 -0
  97. {plover-5.0.0.dev3 → plover-5.0.0rc1}/linux/appimage/apprun.sh +0 -0
  98. {plover-5.0.0.dev3 → plover-5.0.0rc1}/linux/appimage/blacklist.txt +0 -0
  99. {plover-5.0.0.dev3 → plover-5.0.0rc1}/linux/appimage/build.sh +0 -0
  100. {plover-5.0.0.dev3 → plover-5.0.0rc1}/linux/appimage/deps.sh +0 -0
  101. {plover-5.0.0.dev3 → plover-5.0.0rc1}/linux/appimage/pyinfo.py +0 -0
  102. {plover-5.0.0.dev3 → plover-5.0.0rc1}/linux/plover.desktop +0 -0
  103. {plover-5.0.0.dev3 → plover-5.0.0rc1}/news.d/api/.gitignore +0 -0
  104. {plover-5.0.0.dev3 → plover-5.0.0rc1}/news.d/bugfix/.gitignore +0 -0
  105. {plover-5.0.0.dev3 → plover-5.0.0rc1}/news.d/feature/.gitignore +0 -0
  106. {plover-5.0.0.dev3 → plover-5.0.0rc1}/news.d/template.md +0 -0
  107. {plover-5.0.0.dev3 → plover-5.0.0rc1}/osx/README.md +0 -0
  108. {plover-5.0.0.dev3 → plover-5.0.0rc1}/osx/app_resources/Info.plist +0 -0
  109. {plover-5.0.0.dev3 → plover-5.0.0rc1}/osx/app_resources/dist_blacklist.txt +0 -0
  110. {plover-5.0.0.dev3 → plover-5.0.0rc1}/osx/app_resources/plover.icns +0 -0
  111. {plover-5.0.0.dev3 → plover-5.0.0rc1}/osx/app_resources/plover_launcher.c +0 -0
  112. {plover-5.0.0.dev3 → plover-5.0.0rc1}/osx/deps.sh +0 -0
  113. {plover-5.0.0.dev3 → plover-5.0.0rc1}/osx/dmg_resources/background.png +0 -0
  114. {plover-5.0.0.dev3 → plover-5.0.0rc1}/osx/dmg_resources/background.psd +0 -0
  115. {plover-5.0.0.dev3 → plover-5.0.0rc1}/osx/dmg_resources/background@2x.png +0 -0
  116. {plover-5.0.0.dev3 → plover-5.0.0rc1}/osx/dmg_resources/settings.py +0 -0
  117. {plover-5.0.0.dev3 → plover-5.0.0rc1}/osx/make_app.sh +0 -0
  118. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/__main__.py +0 -0
  119. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/assets/american_english_words.txt +0 -0
  120. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/assets/commands.json +0 -0
  121. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/assets/main.json +0 -0
  122. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/assets/plover-icon.svg +0 -0
  123. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/assets/plover.ico +0 -0
  124. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/assets/plover.png +0 -0
  125. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/assets/user.json +0 -0
  126. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/command/__init__.py +0 -0
  127. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/command/set_config.py +0 -0
  128. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/config.py +0 -0
  129. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/dictionary/__init__.py +0 -0
  130. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/dictionary/base.py +0 -0
  131. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/dictionary/helpers.py +0 -0
  132. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/dictionary/json_dict.py +0 -0
  133. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/dictionary/loading_manager.py +0 -0
  134. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/dictionary/rtfcre_dict.py +0 -0
  135. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/dictionary/rtfcre_parse.py +0 -0
  136. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/engine.py +0 -0
  137. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/exception.py +0 -0
  138. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/formatting.py +0 -0
  139. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_none/__init__.py +0 -0
  140. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_none/add_translation.py +0 -0
  141. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_none/engine.py +0 -0
  142. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_none/main.py +0 -0
  143. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/__init__.py +0 -0
  144. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/about_dialog.py +0 -0
  145. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/about_dialog.ui +0 -0
  146. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/add_translation_dialog.py +0 -0
  147. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/add_translation_dialog.ui +0 -0
  148. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/add_translation_widget.py +0 -0
  149. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/add_translation_widget.ui +0 -0
  150. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/config_file_widget.ui +0 -0
  151. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/config_keyboard_widget.ui +0 -0
  152. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/config_serial_widget.ui +0 -0
  153. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/config_window.py +0 -0
  154. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/config_window.ui +0 -0
  155. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/console_widget.py +0 -0
  156. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/console_widget.ui +0 -0
  157. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/dictionaries_widget.py +0 -0
  158. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/dictionaries_widget.ui +0 -0
  159. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/dictionary_editor.py +0 -0
  160. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/dictionary_editor.ui +0 -0
  161. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/engine.py +0 -0
  162. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/info_browser.py +0 -0
  163. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/log_qt.py +0 -0
  164. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/lookup_dialog.py +0 -0
  165. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/lookup_dialog.ui +0 -0
  166. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/machine_options.py +0 -0
  167. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/main.py +0 -0
  168. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/main_window.py +0 -0
  169. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/main_window.ui +0 -0
  170. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/paper_tape.py +0 -0
  171. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/paper_tape.ui +0 -0
  172. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/plugins_manager.py +0 -0
  173. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/plugins_manager.ui +0 -0
  174. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/__init__.py +0 -0
  175. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/add.svg +0 -0
  176. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/dictionary_error.svg +0 -0
  177. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/dictionary_favorite.svg +0 -0
  178. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/dictionary_loading.svg +0 -0
  179. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/dictionary_normal.svg +0 -0
  180. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/dictionary_readonly.svg +0 -0
  181. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/down.svg +0 -0
  182. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/folder.svg +0 -0
  183. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/font_selector.svg +0 -0
  184. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/git.png +0 -0
  185. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/lightbulb.svg +0 -0
  186. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/lookup.svg +0 -0
  187. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/pencil.svg +0 -0
  188. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/pin.svg +0 -0
  189. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/plover.png +0 -0
  190. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/plugins_manager.svg +0 -0
  191. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/reconnect.svg +0 -0
  192. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/remove.svg +0 -0
  193. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/save.svg +0 -0
  194. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/settings.svg +0 -0
  195. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/state-disabled.svg +0 -0
  196. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/state-disconnected.svg +0 -0
  197. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/state-enabled.svg +0 -0
  198. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/tape.svg +0 -0
  199. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/translation_add.svg +0 -0
  200. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/trash.svg +0 -0
  201. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/undo.svg +0 -0
  202. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources/up.svg +0 -0
  203. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/resources.qrc +0 -0
  204. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/run_dialog.py +0 -0
  205. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/run_dialog.ui +0 -0
  206. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/steno_validator.py +0 -0
  207. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/suggestions_dialog.py +0 -0
  208. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/suggestions_dialog.ui +0 -0
  209. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/suggestions_widget.py +0 -0
  210. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/tool.py +0 -0
  211. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/trayicon.py +0 -0
  212. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/gui_qt/utils.py +0 -0
  213. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/i18n.py +0 -0
  214. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/key_combo.py +0 -0
  215. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/log.py +0 -0
  216. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/machine/__init__.py +0 -0
  217. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/machine/base.py +0 -0
  218. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/machine/geminipr.py +0 -0
  219. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/machine/keyboard.py +0 -0
  220. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/machine/keyboard_capture/__init__.py +0 -0
  221. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/machine/keymap.py +0 -0
  222. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/machine/passport.py +0 -0
  223. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/machine/procat.py +0 -0
  224. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/machine/stentura.py +0 -0
  225. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/machine/txbolt.py +0 -0
  226. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/macro/__init__.py +0 -0
  227. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/macro/repeat.py +0 -0
  228. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/macro/retro.py +0 -0
  229. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/macro/undo.py +0 -0
  230. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/messages/es/LC_MESSAGES/plover.po +0 -0
  231. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/messages/fr/LC_MESSAGES/plover.po +0 -0
  232. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/messages/it/LC_MESSAGES/plover.po +0 -0
  233. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/messages/nl/LC_MESSAGES/plover.po +0 -0
  234. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/messages/plover.pot +0 -0
  235. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/messages/zh_tw/LC_MESSAGES/plover.po +0 -0
  236. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/meta/__init__.py +0 -0
  237. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/meta/attach.py +0 -0
  238. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/meta/case.py +0 -0
  239. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/meta/command.py +0 -0
  240. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/meta/conditional.py +0 -0
  241. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/meta/currency.py +0 -0
  242. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/meta/glue.py +0 -0
  243. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/meta/key_combo.py +0 -0
  244. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/meta/mode.py +0 -0
  245. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/meta/punctuation.py +0 -0
  246. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/meta/word_end.py +0 -0
  247. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/misc.py +0 -0
  248. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/orthography.py +0 -0
  249. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/__init__.py +0 -0
  250. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/config.py +0 -0
  251. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/controller.py +0 -0
  252. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/linux/__init__.py +0 -0
  253. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/linux/display_server.py +0 -0
  254. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/linux/i18n.py +0 -0
  255. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/linux/keyboardcontrol.py +0 -0
  256. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/linux/keyboardcontrol_x11.py +0 -0
  257. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/linux/log.py +0 -0
  258. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/linux/log_dbus.py +0 -0
  259. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/linux/serial.py +0 -0
  260. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/linux/wmctrl.py +0 -0
  261. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/linux/wmctrl_x11.py +0 -0
  262. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/osx/__init__.py +0 -0
  263. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/osx/i18n.py +0 -0
  264. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/osx/keyboardcontrol.py +0 -0
  265. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/osx/keyboardlayout.py +0 -0
  266. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/osx/log.py +0 -0
  267. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/osx/serial.py +0 -0
  268. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/osx/wmctrl.py +0 -0
  269. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/windows/__init__.py +0 -0
  270. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/windows/i18n.py +0 -0
  271. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/windows/keyboardcontrol.py +0 -0
  272. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/windows/keyboardlayout.py +0 -0
  273. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/windows/log.py +0 -0
  274. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/windows/serial.py +0 -0
  275. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/oslayer/windows/wmctrl.py +0 -0
  276. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/output/__init__.py +0 -0
  277. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/output/keyboard.py +0 -0
  278. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/plugins_manager/__init__.py +0 -0
  279. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/plugins_manager/__main__.py +0 -0
  280. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/plugins_manager/global_registry.py +0 -0
  281. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/plugins_manager/local_registry.py +0 -0
  282. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/plugins_manager/package_index.py +0 -0
  283. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/plugins_manager/pip_wrapper.py +0 -0
  284. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/plugins_manager/plugin_metadata.py +0 -0
  285. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/plugins_manager/registry.py +0 -0
  286. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/plugins_manager/requests.py +0 -0
  287. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/plugins_manager/utils.py +0 -0
  288. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/registry.py +0 -0
  289. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/resource.py +0 -0
  290. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/scripts/__init__.py +0 -0
  291. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/scripts/dist_main.py +0 -0
  292. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/scripts/main.py +0 -0
  293. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/scripts/send_command.py +0 -0
  294. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/steno.py +0 -0
  295. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/steno_dictionary.py +0 -0
  296. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/suggestions.py +0 -0
  297. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/system/__init__.py +0 -0
  298. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/system/english_stenotype.py +0 -0
  299. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover/translation.py +0 -0
  300. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover.egg-info/SOURCES.txt +0 -0
  301. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover.egg-info/dependency_links.txt +0 -0
  302. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover.egg-info/entry_points.txt +0 -0
  303. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover.egg-info/requires.txt +0 -0
  304. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover.egg-info/top_level.txt +0 -0
  305. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover.egg-info/zip-safe +0 -0
  306. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/__init__.py +0 -0
  307. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/check_requirements.py +0 -0
  308. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/download.py +0 -0
  309. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/functions.sh +0 -0
  310. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/get_pip.py +0 -0
  311. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/install_wheels.py +0 -0
  312. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/pyqt.py +0 -0
  313. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/setup.py +0 -0
  314. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/source_less.py +0 -0
  315. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/testing/__init__.py +0 -0
  316. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/testing/blackbox.py +0 -0
  317. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/testing/dict.py +0 -0
  318. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/testing/output.py +0 -0
  319. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/testing/parametrize.py +0 -0
  320. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/testing/steno.py +0 -0
  321. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/testing/steno_dictionary.py +0 -0
  322. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/tree.py +0 -0
  323. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/trim.py +0 -0
  324. {plover-5.0.0.dev3 → plover-5.0.0rc1}/plover_build_utils/zipdir.py +0 -0
  325. {plover-5.0.0.dev3 → plover-5.0.0rc1}/pyproject.toml +0 -0
  326. {plover-5.0.0.dev3 → plover-5.0.0rc1}/pytest.ini +0 -0
  327. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/bootstrap.txt +0 -0
  328. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/build.txt +0 -0
  329. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/ci.txt +0 -0
  330. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/code_quality.txt +0 -0
  331. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/constraints.txt +0 -0
  332. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/dev.txt +0 -0
  333. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/dist.txt +0 -0
  334. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/dist_extra_gui_qt.txt +0 -0
  335. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/dist_extra_log.txt +0 -0
  336. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/packaging.txt +0 -0
  337. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/release.txt +0 -0
  338. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/setup.txt +0 -0
  339. {plover-5.0.0.dev3 → plover-5.0.0rc1}/reqs/test.txt +0 -0
  340. {plover-5.0.0.dev3 → plover-5.0.0rc1}/setup.cfg +0 -0
  341. {plover-5.0.0.dev3 → plover-5.0.0rc1}/setup.py +0 -0
  342. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/__init__.py +0 -0
  343. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/conftest.py +0 -0
  344. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/gui_qt/__init__.py +0 -0
  345. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/gui_qt/test_dictionaries_widget.py +0 -0
  346. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/gui_qt/test_steno_validator.py +0 -0
  347. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/py37compat.py +0 -0
  348. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_blackbox.py +0 -0
  349. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_command.py +0 -0
  350. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_config.py +0 -0
  351. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_default_dict.py +0 -0
  352. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_engine.py +0 -0
  353. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_formatting.py +0 -0
  354. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_json_dict.py +0 -0
  355. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_key_combo.py +0 -0
  356. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_keyboard.py +0 -0
  357. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_keymap.py +0 -0
  358. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_loading_manager.py +0 -0
  359. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_log.py +0 -0
  360. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_machine.py +0 -0
  361. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_misc.py +0 -0
  362. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_orthography.py +0 -0
  363. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_passport.py +0 -0
  364. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_resource.py +0 -0
  365. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_rtfcre_dict.py +0 -0
  366. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_steno.py +0 -0
  367. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_steno_dictionary.py +0 -0
  368. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_stentura.py +0 -0
  369. {plover-5.0.0.dev3 → plover-5.0.0rc1}/test/test_translation.py +0 -0
  370. {plover-5.0.0.dev3 → plover-5.0.0rc1}/tox.ini +0 -0
  371. {plover-5.0.0.dev3 → plover-5.0.0rc1}/windows/README.md +0 -0
  372. {plover-5.0.0.dev3 → plover-5.0.0rc1}/windows/dist_blacklist.txt +0 -0
  373. {plover-5.0.0.dev3 → plover-5.0.0rc1}/windows/dist_build.sh +0 -0
  374. {plover-5.0.0.dev3 → plover-5.0.0rc1}/windows/dist_deps.sh +0 -0
  375. {plover-5.0.0.dev3 → plover-5.0.0rc1}/windows/installer.bmp +0 -0
  376. {plover-5.0.0.dev3 → plover-5.0.0rc1}/windows/installer.nsi +0 -0
@@ -1,3 +1,22 @@
1
+ # v5.0.0rc1 (2025-09-02)
2
+
3
+
4
+ ## Features
5
+
6
+ ### Linux
7
+
8
+ - Refactor Uinput to use pipe instead of select with timeout. (#1760)
9
+ - Passthrough keyboard shortcuts. (#1761)
10
+ - Uinput: refactor initialization and cleanup. (#1765)
11
+
12
+ ## Bugfixes
13
+
14
+ No significant changes.
15
+
16
+ ## API
17
+
18
+ No significant changes.
19
+
1
20
  # v5.0.0.dev3 (2025-07-14)
2
21
 
3
22
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plover
3
- Version: 5.0.0.dev3
3
+ Version: 5.0.0rc1
4
4
  Summary: Open Source Stenography Software
5
5
  Home-page: http://www.openstenoproject.org/
6
6
  Download-URL: http://www.openstenoproject.org/plover
@@ -123,13 +123,8 @@ jobs completed successfully.
123
123
  ### PyPI release
124
124
 
125
125
  On *tagged* release, the source distribution and wheel are published
126
- to PyPI.
126
+ to PyPI via [Trusted Publishing](https://docs.pypi.org/trusted-publishers/).
127
127
 
128
- For this to work, a valid [PyPI token](https://pypi.org/help/#apitoken)
129
- must be configured: the `PYPI_TOKEN` secret of the `release`
130
- [environment](https://docs.github.com/en/actions/reference/environments)
131
- will be used. Additionally, the optional `PYPI_URL` secret can be set to
132
- use another PyPI compatible index (e.g. Test PyPI).
133
128
 
134
129
  ### GitHub release
135
130
 
@@ -6,7 +6,7 @@ project = "Plover"
6
6
  copyright = "Open Steno Project"
7
7
  author = copyright
8
8
 
9
- release = "5.0.0.dev3"
9
+ release = "5.0.0rc1"
10
10
  version = release
11
11
 
12
12
  # -- General configuration ---------------------------------------------------
@@ -13,7 +13,7 @@ else:
13
13
  # want to translate anyway.
14
14
  _ = lambda s: s
15
15
 
16
- __version__ = "5.0.0.dev3"
16
+ __version__ = "5.0.0rc1"
17
17
  __copyright__ = "(C) Open Steno Project"
18
18
  __url__ = "http://www.openstenoproject.org/"
19
19
  __download_url__ = "http://www.openstenoproject.org/plover"
@@ -1,6 +1,16 @@
1
- from evdev import UInput, ecodes as e, util, InputDevice, list_devices
1
+ from evdev import (
2
+ UInput,
3
+ ecodes as e,
4
+ util,
5
+ InputDevice,
6
+ list_devices,
7
+ InputEvent,
8
+ KeyEvent,
9
+ )
2
10
  import threading
3
- from select import select
11
+ import os
12
+ import selectors
13
+
4
14
  from psutil import process_iter
5
15
 
6
16
  from plover.output.keyboard import GenericKeyboardEmulation
@@ -320,6 +330,17 @@ KEYCODE_TO_KEY = dict(
320
330
  zip(LAYOUTS[DEFAULT_LAYOUT].values(), LAYOUTS[DEFAULT_LAYOUT].keys())
321
331
  )
322
332
 
333
+ MODIFIER_KEY_CODES: set[int] = {
334
+ e.KEY_LEFTSHIFT,
335
+ e.KEY_RIGHTSHIFT,
336
+ e.KEY_LEFTCTRL,
337
+ e.KEY_RIGHTCTRL,
338
+ e.KEY_LEFTALT,
339
+ e.KEY_RIGHTALT,
340
+ e.KEY_LEFTMETA,
341
+ e.KEY_RIGHTMETA,
342
+ }
343
+
323
344
 
324
345
  class KeyboardEmulation(GenericKeyboardEmulation):
325
346
  def __init__(self):
@@ -412,21 +433,30 @@ class KeyboardEmulation(GenericKeyboardEmulation):
412
433
 
413
434
 
414
435
  class KeyboardCapture(Capture):
436
+ _selector: selectors.DefaultSelector
437
+ _device_thread: threading.Thread | None
438
+ # Pipes to signal `_run` thread to stop
439
+ _device_thread_read_pipe: int | None
440
+ _device_thread_write_pipe: int | None
441
+
415
442
  def __init__(self):
416
443
  super().__init__()
417
- # This is based on the example from the python-evdev documentation, using the first of the three alternative methods: https://python-evdev.readthedocs.io/en/latest/tutorial.html#reading-events-from-multiple-devices-using-select
418
444
  self._devices = self._get_devices()
419
- self._running = False
420
- self._thread = None
445
+
446
+ self._selector = selectors.DefaultSelector()
447
+ self._device_thread = None
448
+ self._device_thread_read_pipe = None
449
+ self._device_thread_write_pipe = None
450
+
421
451
  self._res = util.find_ecodes_by_regex(r"KEY_.*")
422
452
  self._ui = UInput(self._res)
423
- self._suppressed_keys = []
453
+ self._suppressed_keys = set()
424
454
  # The keycodes from evdev, e.g. e.KEY_A refers to the *physical* a, which corresponds with the qwerty layout.
425
455
 
426
456
  def _get_devices(self):
427
457
  input_devices = [InputDevice(path) for path in list_devices()]
428
458
  keyboard_devices = [dev for dev in input_devices if self._filter_devices(dev)]
429
- return {dev.fd: dev for dev in keyboard_devices}
459
+ return keyboard_devices
430
460
 
431
461
  def _filter_devices(self, device):
432
462
  """
@@ -451,7 +481,7 @@ class KeyboardCapture(Capture):
451
481
  There is likely a race condition here between checking active keys and
452
482
  actually grabbing the device, but it appears to work fine.
453
483
  """
454
- for device in self._devices.values():
484
+ for device in self._devices:
455
485
  if len(device.active_keys()) > 0:
456
486
  for _ in device.read_loop():
457
487
  if len(device.active_keys()) == 0:
@@ -461,26 +491,50 @@ class KeyboardCapture(Capture):
461
491
 
462
492
  def _ungrab_devices(self):
463
493
  """Ungrab all devices. Handles all exceptions when ungrabbing."""
464
- for device in self._devices.values():
494
+ for device in self._devices:
465
495
  try:
466
496
  device.ungrab()
467
497
  except:
468
498
  log.debug("failed to ungrab device", exc_info=True)
469
499
 
470
500
  def start(self):
501
+ # Exception handling note: cancel() will eventually be called when the
502
+ # machine reconnect button is pressed or when the machine is changed.
503
+ # Therefore, cancel() does not need to be called in the except block.
471
504
  try:
472
505
  self._grab_devices()
473
- except Exception as e:
506
+ self._device_thread_read_pipe, self._device_thread_write_pipe = os.pipe()
507
+ self._selector.register(self._device_thread_read_pipe, selectors.EVENT_READ)
508
+ for device in self._devices:
509
+ self._selector.register(device, selectors.EVENT_READ)
510
+
511
+ self._device_thread = threading.Thread(target=self._run)
512
+ self._device_thread.start()
513
+ except Exception:
474
514
  self._ungrab_devices()
515
+ self._ui.close()
475
516
  raise
476
- self._running = True
477
- self._thread = threading.Thread(target=self._run)
478
- self._thread.start()
479
517
 
480
518
  def cancel(self):
481
- self._running = False
482
- if self._thread is not None:
483
- self._thread.join()
519
+ if (
520
+ self._device_thread_read_pipe is None
521
+ or self._device_thread_write_pipe is None
522
+ ):
523
+ # The only way for these pipes to be None is if pipe creation in start() failed
524
+ # In that case, no other code after pipe creation would have run
525
+ # and no cleanup is required
526
+ return
527
+ try:
528
+ # Write some arbitrary data to the pipe to signal the _run thread to stop
529
+ os.write(self._device_thread_write_pipe, b"a")
530
+ if self._device_thread is not None:
531
+ self._device_thread.join()
532
+ self._selector.close()
533
+ except Exception:
534
+ log.debug("error stopping KeyboardCapture", exc_info=True)
535
+ finally:
536
+ os.close(self._device_thread_read_pipe)
537
+ os.close(self._device_thread_write_pipe)
484
538
 
485
539
  def suppress(self, suppressed_keys=()):
486
540
  """
@@ -488,31 +542,77 @@ class KeyboardCapture(Capture):
488
542
  are passed through to a UInput device and emulated, while keys in this list get sent to plover.
489
543
  It does add a little bit of delay, but that is not noticeable.
490
544
  """
491
- self._suppressed_keys = suppressed_keys
545
+ self._suppressed_keys = set(suppressed_keys)
492
546
 
493
547
  def _run(self):
548
+ keys_pressed_with_modifier: set[int] = set()
549
+ down_modifier_keys: set[int] = set()
550
+
551
+ def _process_key_event(event: InputEvent) -> tuple[str | None, bool]:
552
+ """
553
+ Processes an InputEvent to determine which key Plover should receive
554
+ and whether the event should be suppressed.
555
+ Considers pressed modifiers and Plover's suppressed keys.
556
+ Returns a tuple of (key_to_send_to_plover, suppress)
557
+ """
558
+ if not self._suppressed_keys:
559
+ # No keys are suppressed
560
+ # Always send to Plover so that it can handle global shortcuts like PLOVER_TOGGLE (PHROLG)
561
+ return KEYCODE_TO_KEY.get(event.code, None), False
562
+ if event.code in MODIFIER_KEY_CODES:
563
+ # Can't use if-else because there is a third case: key_hold
564
+ if event.value == KeyEvent.key_down:
565
+ down_modifier_keys.add(event.code)
566
+ elif event.value == KeyEvent.key_up:
567
+ down_modifier_keys.discard(event.code)
568
+ return None, False
569
+ key = KEYCODE_TO_KEY.get(event.code, None)
570
+ if key is None:
571
+ # Key is unhandled. Passthrough
572
+ return None, False
573
+ if event.value == KeyEvent.key_down and down_modifier_keys:
574
+ keys_pressed_with_modifier.add(event.code)
575
+ return None, False
576
+ if (
577
+ event.value == KeyEvent.key_up
578
+ and event.code in keys_pressed_with_modifier
579
+ ):
580
+ # Must pass through key up event if key was pressed with modifier
581
+ # or else it will stay pressed down and start repeating.
582
+ # Must release even if modifier key was released first
583
+ keys_pressed_with_modifier.discard(event.code)
584
+ return None, False
585
+ suppress = key in self._suppressed_keys
586
+ return key, suppress
587
+
494
588
  try:
495
- while self._running:
496
- """
497
- The select() call blocks the loop until it gets an input, which meant that the keyboard
498
- had to be pressed once after executing `cancel()`. Now, there is a 1 second delay instead
499
- FIXME: maybe use one of the other options to avoid the timeout
500
- https://python-evdev.readthedocs.io/en/latest/tutorial.html#reading-events-from-multiple-devices-using-select
501
- """
502
- r, _, _ = select(self._devices, [], [], 1)
503
- for fd in r:
504
- for event in self._devices[fd].read():
589
+ while True:
590
+ for key, events in self._selector.select():
591
+ if key.fd == self._device_thread_read_pipe:
592
+ # Stop this thread
593
+ return
594
+ assert isinstance(key.fileobj, InputDevice)
595
+ device: InputDevice = key.fileobj
596
+ for event in device.read():
505
597
  if event.type == e.EV_KEY:
506
- if event.code in KEYCODE_TO_KEY:
507
- key_name = KEYCODE_TO_KEY[event.code]
508
- if key_name in self._suppressed_keys:
509
- pressed = event.value == 1
510
- (self.key_down if pressed else self.key_up)(
511
- key_name
512
- )
513
- continue # Go to the next iteration, skipping the below code:
514
- self._ui.write(e.EV_KEY, event.code, event.value)
515
- self._ui.syn()
598
+ key_to_send_to_plover, suppress = _process_key_event(event)
599
+ if key_to_send_to_plover is not None:
600
+ # Always send keys to Plover when no keys suppressed.
601
+ # This is required for global shortcuts like
602
+ # Plover toggle (PHROLG) when Plover is disabled.
603
+ # Note: Must explicitly check key_up or key_down
604
+ # because there is a third case: key_hold
605
+ if event.value == KeyEvent.key_down:
606
+ self.key_down(key_to_send_to_plover)
607
+ elif event.value == KeyEvent.key_up:
608
+ self.key_up(key_to_send_to_plover)
609
+ if suppress:
610
+ # Skip rest of loop to prevent event from
611
+ # being passed through
612
+ continue
613
+
614
+ # Passthrough event
615
+ self._ui.write_event(event)
516
616
  except:
517
617
  log.error("keyboard capture error", exc_info=True)
518
618
  finally:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plover
3
- Version: 5.0.0.dev3
3
+ Version: 5.0.0rc1
4
4
  Summary: Open Source Stenography Software
5
5
  Home-page: http://www.openstenoproject.org/
6
6
  Download-URL: http://www.openstenoproject.org/plover
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes