ok-script 2.0.2__tar.gz → 2.0.3__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 (360) hide show
  1. {ok_script-2.0.2/ok_script.egg-info → ok_script-2.0.3}/PKG-INFO +1 -1
  2. {ok_script-2.0.2 → ok_script-2.0.3}/ok/__init__.py +53 -24
  3. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/windows_graphics.py +21 -2
  4. {ok_script-2.0.2 → ok_script-2.0.3}/ok/task/TaskExecutor.py +32 -8
  5. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/overlay/win32_gdi.py +364 -64
  6. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/MainWindow.py +29 -4
  7. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/debug/OverlayWidget.py +1 -79
  8. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/events.py +12 -1
  9. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/en_US.qm +0 -0
  10. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/en_US.ts +0 -24
  11. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/es_ES.qm +0 -0
  12. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/es_ES.ts +0 -24
  13. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/ja_JP.qm +0 -0
  14. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/ja_JP.ts +0 -24
  15. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/ko_KR.qm +0 -0
  16. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/ko_KR.ts +0 -24
  17. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/zh_CN.qm +0 -0
  18. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/zh_CN.ts +0 -24
  19. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/zh_TW.qm +0 -0
  20. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/zh_TW.ts +0 -24
  21. ok_script-2.0.3/ok/ui/qt/resources.py +18978 -0
  22. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/start/StartTab.py +24 -28
  23. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/OneTimeTaskTab.py +1 -0
  24. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/TaskCard.py +10 -1
  25. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/TriggerTaskTab.py +1 -0
  26. ok_script-2.0.3/ok/ui/web/static/app.js +11 -0
  27. ok_script-2.0.3/ok/ui/web/static/index.css +1 -0
  28. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/handler.py +65 -18
  29. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/process.py +234 -19
  30. {ok_script-2.0.2 → ok_script-2.0.3/ok_script.egg-info}/PKG-INFO +1 -1
  31. {ok_script-2.0.2 → ok_script-2.0.3}/ok_script.egg-info/SOURCES.txt +3 -0
  32. ok_script-2.0.3/tests/test_handler.py +76 -0
  33. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_main_window_startup_tab.py +9 -1
  34. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_ok_mutex.py +11 -2
  35. ok_script-2.0.3/tests/test_overlay_custom_draw.py +157 -0
  36. ok_script-2.0.3/tests/test_process_mutex.py +78 -0
  37. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_qt_events.py +13 -0
  38. ok_script-2.0.3/tests/test_start_tab_overlay.py +17 -0
  39. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_task_executor_queue.py +14 -1
  40. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_task_ui.py +23 -0
  41. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_web_app.py +61 -3
  42. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_windows_graphics_capture.py +17 -0
  43. ok_script-2.0.2/ok/ui/qt/resources.py +0 -19337
  44. ok_script-2.0.2/ok/ui/web/static/app.js +0 -11
  45. ok_script-2.0.2/ok/ui/web/static/index.css +0 -1
  46. ok_script-2.0.2/tests/test_overlay_custom_draw.py +0 -61
  47. {ok_script-2.0.2 → ok_script-2.0.3}/LICENSE.txt +0 -0
  48. {ok_script-2.0.2 → ok_script-2.0.3}/MANIFEST.in +0 -0
  49. {ok_script-2.0.2 → ok_script-2.0.3}/README.md +0 -0
  50. {ok_script-2.0.2 → ok_script-2.0.3}/diagnostics/qq_trace.py +0 -0
  51. {ok_script-2.0.2 → ok_script-2.0.3}/ok/__main__.py +0 -0
  52. {ok_script-2.0.2 → ok_script-2.0.3}/ok/alas/__init__.py +0 -0
  53. {ok_script-2.0.2 → ok_script-2.0.3}/ok/alas/emulator_base.py +0 -0
  54. {ok_script-2.0.2 → ok_script-2.0.3}/ok/alas/emulator_windows.py +0 -0
  55. {ok_script-2.0.2 → ok_script-2.0.3}/ok/alas/platform_windows.py +0 -0
  56. {ok_script-2.0.2 → ok_script-2.0.3}/ok/alas/utils.py +0 -0
  57. {ok_script-2.0.2 → ok_script-2.0.3}/ok/capture/__init__.py +0 -0
  58. {ok_script-2.0.2 → ok_script-2.0.3}/ok/capture/adb/__init__.py +0 -0
  59. {ok_script-2.0.2 → ok_script-2.0.3}/ok/capture/adb/deep.py +0 -0
  60. {ok_script-2.0.2 → ok_script-2.0.3}/ok/capture/adb/minitouch.py +0 -0
  61. {ok_script-2.0.2 → ok_script-2.0.3}/ok/capture/adb/nemu_ipc.py +0 -0
  62. {ok_script-2.0.2 → ok_script-2.0.3}/ok/capture/adb/nemu_utils.py +0 -0
  63. {ok_script-2.0.2 → ok_script-2.0.3}/ok/capture/adb/pool.py +0 -0
  64. {ok_script-2.0.2 → ok_script-2.0.3}/ok/capture/adb/timer.py +0 -0
  65. {ok_script-2.0.2 → ok_script-2.0.3}/ok/capture/adb/util.py +0 -0
  66. {ok_script-2.0.2 → ok_script-2.0.3}/ok/capture/windows/__init__.py +0 -0
  67. {ok_script-2.0.2 → ok_script-2.0.3}/ok/capture/windows/d3d11.py +0 -0
  68. {ok_script-2.0.2 → ok_script-2.0.3}/ok/capture/windows/dump.py +0 -0
  69. {ok_script-2.0.2 → ok_script-2.0.3}/ok/cli.py +0 -0
  70. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/__init__.py +0 -0
  71. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/config_schema.py +0 -0
  72. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/downloads.py +0 -0
  73. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/events.py +0 -0
  74. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/icons.py +0 -0
  75. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/notifications.py +0 -0
  76. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/screenshot.py +0 -0
  77. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/script_editing.py +0 -0
  78. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/script_packager.py +0 -0
  79. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/script_templates.py +0 -0
  80. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/start_controller.py +0 -0
  81. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/task_manager.py +0 -0
  82. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/template_store.py +0 -0
  83. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/translation.py +0 -0
  84. {ok_script-2.0.2 → ok_script-2.0.3}/ok/core/ui_config.py +0 -0
  85. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/DeviceManager.py +0 -0
  86. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/__init__.py +0 -0
  87. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture.py +0 -0
  88. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/__init__.py +0 -0
  89. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/adb.py +0 -0
  90. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/base.py +0 -0
  91. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/bitblt.py +0 -0
  92. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/bitblt_utils.py +0 -0
  93. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/browser.py +0 -0
  94. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/desktop_duplication.py +0 -0
  95. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/hwnd_window.py +0 -0
  96. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/image.py +0 -0
  97. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/nemu_ipc.py +0 -0
  98. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/types.py +0 -0
  99. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/capture_methods/update.py +0 -0
  100. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction.py +0 -0
  101. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction_methods/__init__.py +0 -0
  102. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction_methods/adb.py +0 -0
  103. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction_methods/base.py +0 -0
  104. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction_methods/browser.py +0 -0
  105. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction_methods/do_nothing.py +0 -0
  106. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction_methods/foreground_post_message.py +0 -0
  107. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction_methods/genshin.py +0 -0
  108. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction_methods/keys.py +0 -0
  109. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction_methods/post_message.py +0 -0
  110. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction_methods/pydirect.py +0 -0
  111. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction_methods/pynput.py +0 -0
  112. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/interaction_methods/swipe.py +0 -0
  113. {ok_script-2.0.2 → ok_script-2.0.3}/ok/device/intercation.py +0 -0
  114. {ok_script-2.0.2 → ok_script-2.0.3}/ok/feature/Box.py +0 -0
  115. {ok_script-2.0.2 → ok_script-2.0.3}/ok/feature/Feature.py +0 -0
  116. {ok_script-2.0.2 → ok_script-2.0.3}/ok/feature/FeatureSet.py +0 -0
  117. {ok_script-2.0.2 → ok_script-2.0.3}/ok/feature/__init__.py +0 -0
  118. {ok_script-2.0.2 → ok_script-2.0.3}/ok/gui/__init__.py +0 -0
  119. {ok_script-2.0.2 → ok_script-2.0.3}/ok/gui/util/pyappify_startup.py +0 -0
  120. {ok_script-2.0.2 → ok_script-2.0.3}/ok/notification/__init__.py +0 -0
  121. {ok_script-2.0.2 → ok_script-2.0.3}/ok/notification/manager.py +0 -0
  122. {ok_script-2.0.2 → ok_script-2.0.3}/ok/notification/messenger_images.py +0 -0
  123. {ok_script-2.0.2 → ok_script-2.0.3}/ok/notification/pipeline.py +0 -0
  124. {ok_script-2.0.2 → ok_script-2.0.3}/ok/notification/ppocr.py +0 -0
  125. {ok_script-2.0.2 → ok_script-2.0.3}/ok/notification/providers.py +0 -0
  126. {ok_script-2.0.2 → ok_script-2.0.3}/ok/notification/system.py +0 -0
  127. {ok_script-2.0.2 → ok_script-2.0.3}/ok/notification/windows_messenger.py +0 -0
  128. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ocr/__init__.py +0 -0
  129. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ocr/download_paddle_model.py +0 -0
  130. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
  131. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
  132. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
  133. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
  134. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
  135. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
  136. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
  137. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
  138. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
  139. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Media/__init__.py +0 -0
  140. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
  141. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Security/__init__.py +0 -0
  142. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
  143. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/Storage/__init__.py +0 -0
  144. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/UI/ViewManagement/__init__.py +0 -0
  145. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/UI/__init__.py +0 -0
  146. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/Windows/__init__.py +0 -0
  147. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/__init__.py +0 -0
  148. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/delegate.py +0 -0
  149. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/export.py +0 -0
  150. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/idldsl.py +0 -0
  151. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/inspectable.py +0 -0
  152. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/roapi.py +0 -0
  153. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/types.py +0 -0
  154. {ok_script-2.0.2 → ok_script-2.0.3}/ok/rotypes/winstring.py +0 -0
  155. {ok_script-2.0.2 → ok_script-2.0.3}/ok/task/DiagnosisTask.py +0 -0
  156. {ok_script-2.0.2 → ok_script-2.0.3}/ok/task/__init__.py +0 -0
  157. {ok_script-2.0.2 → ok_script-2.0.3}/ok/task/exceptions.py +0 -0
  158. {ok_script-2.0.2 → ok_script-2.0.3}/ok/task/task.py +0 -0
  159. {ok_script-2.0.2 → ok_script-2.0.3}/ok/task/web.py +0 -0
  160. {ok_script-2.0.2 → ok_script-2.0.3}/ok/test/OKTestRunner.py +0 -0
  161. {ok_script-2.0.2 → ok_script-2.0.3}/ok/test/RunTests.py +0 -0
  162. {ok_script-2.0.2 → ok_script-2.0.3}/ok/test/TaskTestCase.py +0 -0
  163. {ok_script-2.0.2 → ok_script-2.0.3}/ok/test/__init__.py +0 -0
  164. {ok_script-2.0.2 → ok_script-2.0.3}/ok/third_party/__init__.py +0 -0
  165. {ok_script-2.0.2 → ok_script-2.0.3}/ok/third_party/paperclip.py +0 -0
  166. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/__init__.py +0 -0
  167. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/overlay/__init__.py +0 -0
  168. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/Communicate.py +0 -0
  169. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/MessageWindow.py +0 -0
  170. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/StartController.py +0 -0
  171. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/TabTitles.py +0 -0
  172. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/__init__.py +0 -0
  173. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/about/AboutTab.py +0 -0
  174. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/about/HttpTextEdit.py +0 -0
  175. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/about/LinksBar.py +0 -0
  176. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/about/ProjectCard.py +0 -0
  177. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/about/UpdateCard.py +0 -0
  178. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/about/VersionCard.py +0 -0
  179. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/about/__init__.py +0 -0
  180. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/common/OKIcon.py +0 -0
  181. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/common/__init__.py +0 -0
  182. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/common/accent_color.py +0 -0
  183. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/common/config.py +0 -0
  184. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/common/design_system.py +0 -0
  185. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/common/icons.py +0 -0
  186. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/common/style_sheet.py +0 -0
  187. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/debug/DebugTab.py +0 -0
  188. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/debug/RunCodeTab.py +0 -0
  189. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/debug/Screenshot.py +0 -0
  190. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/debug/__init__.py +0 -0
  191. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/GettextTranslator.py +0 -0
  192. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/__init__.py +0 -0
  193. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/path.py +0 -0
  194. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/i18n/update.py +0 -0
  195. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/overlay/OverlayWindow.py +0 -0
  196. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/overlay/__init__.py +0 -0
  197. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/__init__.py +0 -0
  198. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/dark/card.qss +0 -0
  199. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/dark/discord.svg +0 -0
  200. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/dark/heart.svg +0 -0
  201. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/dark/message_window.qss +0 -0
  202. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/dark/setting_interface.qss +0 -0
  203. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/dark/status_bar.qss +0 -0
  204. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/dark/stop.svg +0 -0
  205. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/dark/tab.qss +0 -0
  206. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/light/card.qss +0 -0
  207. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/light/discord.svg +0 -0
  208. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/light/heart.svg +0 -0
  209. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/light/message_window.qss +0 -0
  210. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/light/setting_interface.qss +0 -0
  211. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/light/status_bar.qss +0 -0
  212. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/light/stop.svg +0 -0
  213. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qss/light/tab.qss +0 -0
  214. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/qt.qrc +0 -0
  215. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/settings/GlobalConfigCard.py +0 -0
  216. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/settings/GlobalConfigTab.py +0 -0
  217. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/settings/SettingTab.py +0 -0
  218. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/settings/__init__.py +0 -0
  219. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/start/LogWindow.py +0 -0
  220. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/start/SelectCaptureListView.py +0 -0
  221. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/start/SelectInteractionListView.py +0 -0
  222. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/start/StartCard.py +0 -0
  223. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/start/__init__.py +0 -0
  224. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/ConfigCard.py +0 -0
  225. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/ConfigItemFactory.py +0 -0
  226. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/ConfigLabelAndWidget.py +0 -0
  227. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/EditTaskTab.py +0 -0
  228. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/LabelAndButtons.py +0 -0
  229. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/LabelAndDoubleSpinBox.py +0 -0
  230. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/LabelAndDropDown.py +0 -0
  231. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/LabelAndFileSelector.py +0 -0
  232. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/LabelAndGlobal.py +0 -0
  233. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/LabelAndLineEdit.py +0 -0
  234. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/LabelAndList.py +0 -0
  235. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/LabelAndMultiSelection.py +0 -0
  236. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/LabelAndSpinBox.py +0 -0
  237. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/LabelAndSwitchButton.py +0 -0
  238. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/LabelAndTextEdit.py +0 -0
  239. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/LabelAndWidget.py +0 -0
  240. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/MarkUpWindow.py +0 -0
  241. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/ModifyListDialog.py +0 -0
  242. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/ModifyListItem.py +0 -0
  243. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/PythonHighlighter.py +0 -0
  244. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/RecordScript.py +0 -0
  245. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/ScheduleTaskTab.py +0 -0
  246. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/ScriptPackager.py +0 -0
  247. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/StartButton.py +0 -0
  248. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/TaskManger.py +0 -0
  249. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/TaskOpButton.py +0 -0
  250. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/TaskTab.py +0 -0
  251. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/TemplateFactory.py +0 -0
  252. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/TemplateTab.py +0 -0
  253. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/TooltipTableWidget.py +0 -0
  254. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/tasks/__init__.py +0 -0
  255. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/util/Alert.py +0 -0
  256. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/util/InitWorker.py +0 -0
  257. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/util/__init__.py +0 -0
  258. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/util/app.py +0 -0
  259. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/util/download.py +0 -0
  260. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/util/pip_util.py +0 -0
  261. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/util/pyappify_startup.py +0 -0
  262. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/util/touch_scroll.py +0 -0
  263. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/util/windows_thumbnail.py +0 -0
  264. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/BaseLoading.py +0 -0
  265. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/BaseWindow.py +0 -0
  266. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/Card.py +0 -0
  267. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/CustomTab.py +0 -0
  268. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/EmptyCard.py +0 -0
  269. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/ExpandCardLayout.py +0 -0
  270. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/FlowLayout.py +0 -0
  271. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/FramelessDialog.py +0 -0
  272. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/ImageWidget.py +0 -0
  273. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/ListTableWidgetItem.py +0 -0
  274. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/NumericTableWidgetItem.py +0 -0
  275. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/OkCompactSpinBox.py +0 -0
  276. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/SortingTableWidgetItem.py +0 -0
  277. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/StartLoadingDialog.py +0 -0
  278. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/StatusBar.py +0 -0
  279. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/Tab.py +0 -0
  280. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/TabWidget.py +0 -0
  281. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/UpdateConfigWidgetItem.py +0 -0
  282. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/WidgetWithVLabel.py +0 -0
  283. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/YesNonWidgetItem.py +0 -0
  284. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/qt/widget/__init__.py +0 -0
  285. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/web/__init__.py +0 -0
  286. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/web/app.py +0 -0
  287. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/web/requirements.py +0 -0
  288. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/web/server.py +0 -0
  289. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/web/static/chunk-fluent.js +0 -0
  290. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/web/static/chunk-react.js +0 -0
  291. {ok_script-2.0.2 → ok_script-2.0.3}/ok/ui/web/static/index.html +0 -0
  292. {ok_script-2.0.2 → ok_script-2.0.3}/ok/update/__init__.py +0 -0
  293. {ok_script-2.0.2 → ok_script-2.0.3}/ok/update/copy_ok_folder.py +0 -0
  294. {ok_script-2.0.2 → ok_script-2.0.3}/ok/update/inline_ok_requirements.py +0 -0
  295. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/Analytics.py +0 -0
  296. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/GlobalConfig.py +0 -0
  297. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/__init__.py +0 -0
  298. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/blur.py +0 -0
  299. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/clazz.py +0 -0
  300. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/collection.py +0 -0
  301. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/color.py +0 -0
  302. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/config.py +0 -0
  303. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/explorer.py +0 -0
  304. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/file.py +0 -0
  305. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/gpu_driver_settings.py +0 -0
  306. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/i18n.py +0 -0
  307. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/logger.py +0 -0
  308. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/partial_sync_repo.py +0 -0
  309. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/print_hwnd.py +0 -0
  310. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/window.py +0 -0
  311. {ok_script-2.0.2 → ok_script-2.0.3}/ok/util/windows_schedule.py +0 -0
  312. {ok_script-2.0.2 → ok_script-2.0.3}/ok_script.egg-info/dependency_links.txt +0 -0
  313. {ok_script-2.0.2 → ok_script-2.0.3}/ok_script.egg-info/entry_points.txt +0 -0
  314. {ok_script-2.0.2 → ok_script-2.0.3}/ok_script.egg-info/not-zip-safe +0 -0
  315. {ok_script-2.0.2 → ok_script-2.0.3}/ok_script.egg-info/requires.txt +0 -0
  316. {ok_script-2.0.2 → ok_script-2.0.3}/ok_script.egg-info/top_level.txt +0 -0
  317. {ok_script-2.0.2 → ok_script-2.0.3}/pyproject.toml +0 -0
  318. {ok_script-2.0.2 → ok_script-2.0.3}/scripts/generate_web_i18n.py +0 -0
  319. {ok_script-2.0.2 → ok_script-2.0.3}/setup.cfg +0 -0
  320. {ok_script-2.0.2 → ok_script-2.0.3}/setup.py +0 -0
  321. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_accent_color.py +0 -0
  322. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_app.py +0 -0
  323. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_base_interaction.py +0 -0
  324. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_blur.py +0 -0
  325. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_box.py +0 -0
  326. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_capture_update.py +0 -0
  327. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_cli.py +0 -0
  328. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_config_card.py +0 -0
  329. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_core_events.py +0 -0
  330. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_core_ui_services.py +0 -0
  331. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_device_manager.py +0 -0
  332. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_expand_card_layout.py +0 -0
  333. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_explorer.py +0 -0
  334. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_global_config.py +0 -0
  335. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_gpu_driver_settings.py +0 -0
  336. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_headless_imports.py +0 -0
  337. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_inline_ok_requirements.py +0 -0
  338. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_logger.py +0 -0
  339. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_main_window_notifications.py +0 -0
  340. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_main_window_system_theme.py +0 -0
  341. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_missing_frame.py +0 -0
  342. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_navigation_state.py +0 -0
  343. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_nemu_ipc_capture.py +0 -0
  344. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_notifications.py +0 -0
  345. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_package_metadata.py +0 -0
  346. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_process.py +0 -0
  347. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_pyappify_startup_update.py +0 -0
  348. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_qt_legacy_imports.py +0 -0
  349. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_qt_page_layout.py +0 -0
  350. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_runtime_startup.py +0 -0
  351. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_start_controller.py +0 -0
  352. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_template_tab.py +0 -0
  353. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_touch_scroll.py +0 -0
  354. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_translation_fallback.py +0 -0
  355. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_ui_config.py +0 -0
  356. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_web_i18n.py +0 -0
  357. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_web_server.py +0 -0
  358. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_web_task_tabs.py +0 -0
  359. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_web_ui_pages.py +0 -0
  360. {ok_script-2.0.2 → ok_script-2.0.3}/tests/test_web_ui_tasks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ok-script
3
- Version: 2.0.2
3
+ Version: 2.0.3
4
4
  Summary: Automation with Computer Vision for Python
5
5
  Author-email: ok-oldking <firedcto@gmail.com>
6
6
  License: ok-script License
@@ -217,7 +217,6 @@ _OK_CONFIG_DEFAULTS = {
217
217
  'window_maximized': False,
218
218
  'navigation_expanded': True,
219
219
  'use_overlay': False,
220
- 'show_overlay_logs': True,
221
220
  }
222
221
 
223
222
 
@@ -226,24 +225,33 @@ def _create_ok_config(config):
226
225
  from ok.util.config import Config
227
226
 
228
227
  defaults = dict(_OK_CONFIG_DEFAULTS)
229
- for key in ('use_overlay', 'show_overlay_logs'):
230
- if key in config:
231
- defaults[key] = bool(config[key])
228
+ if 'use_overlay' in config:
229
+ defaults['use_overlay'] = bool(config['use_overlay'])
232
230
  return Config('_ok', defaults)
233
231
 
234
232
 
235
233
  class _OverlayConfigMixin:
236
234
  def overlay_state(self):
237
- return {
238
- 'boxes': bool(self.ok_config.get('use_overlay', False)),
239
- 'logs': bool(self.ok_config.get('show_overlay_logs', True)),
240
- }
235
+ return {'boxes': bool(self.ok_config.get('use_overlay', False))}
241
236
 
242
237
  def initialize_overlay(self):
243
238
  """Apply persisted overlay state independently of the active UI."""
244
- if self.ok_config.get('use_overlay', False) or callable(self.config.get('blur_area')):
239
+ if self.ok_config.get('use_overlay', False):
245
240
  overlay = self.get_overlay_view()
246
- overlay.set_boxes_enabled(self.ok_config.get('use_overlay', False))
241
+ if overlay is not None:
242
+ overlay.set_boxes_enabled(True)
243
+
244
+ def _close_overlay(self, wait=True):
245
+ overlay = self.overlay_window
246
+ if overlay is None:
247
+ return
248
+ from ok.core.events import communicate
249
+ communicate.window.disconnect(overlay.update_overlay)
250
+ self.overlay_window = None
251
+ if wait:
252
+ overlay.close()
253
+ else:
254
+ overlay.close(wait=False)
247
255
 
248
256
  def sync_overlay_source(self, *_args):
249
257
  """Refresh a lazy overlay from the currently selected capture window."""
@@ -254,18 +262,18 @@ class _OverlayConfigMixin:
254
262
  overlay.sync_source_window(getattr(device_manager, 'hwnd_window', None))
255
263
 
256
264
  def set_overlay_setting(self, name, value):
257
- key = {'boxes': 'use_overlay', 'logs': 'show_overlay_logs'}.get(name)
258
- if key is None:
265
+ if name != 'boxes':
259
266
  raise ValueError(f'Unknown overlay setting: {name}')
260
267
 
261
- self.ok_config[key] = bool(value)
268
+ self.ok_config['use_overlay'] = bool(value)
262
269
  overlay = self.overlay_window
263
270
  if name == 'boxes' and value:
264
271
  overlay = self.get_overlay_view()
272
+ elif name == 'boxes' and not value and overlay is not None:
273
+ self._close_overlay()
274
+ return self.overlay_state()
265
275
  if overlay is not None:
266
276
  self.sync_overlay_source()
267
- # This also schedules a repaint so a changed log setting takes
268
- # effect immediately in the native overlay.
269
277
  overlay.set_boxes_enabled(self.ok_config.get('use_overlay', False))
270
278
  return self.overlay_state()
271
279
 
@@ -333,9 +341,8 @@ class App(_OverlayConfigMixin):
333
341
  logger.debug('init app end')
334
342
 
335
343
  def quit(self):
336
- if self.overlay_window is not None:
337
- self.overlay_window.close()
338
344
  self.exit_event.set()
345
+ self._close_overlay(wait=False)
339
346
  self._close_device_manager()
340
347
  from PySide6.QtCore import QMetaObject, Qt
341
348
  QMetaObject.invokeMethod(self.app, "quit", Qt.QueuedConnection)
@@ -403,16 +410,28 @@ class App(_OverlayConfigMixin):
403
410
  self.show_message_window(title, content)
404
411
 
405
412
  def update_overlay(self, visible, x, y, window_width, window_height, width, height, scaling):
406
- overlay_view = self.get_overlay_view()
413
+ if not self.ok_config.get('use_overlay', False):
414
+ # Treat the setting as an absolute lifecycle gate. In particular,
415
+ # a configured blur callback must not resurrect a disabled native
416
+ # window (and its input/expiry workers).
417
+ if self.overlay_window is not None:
418
+ self._close_overlay(wait=False)
419
+ return
420
+ overlay_view = self.overlay_window
421
+ if overlay_view is None:
422
+ overlay_view = self.get_overlay_view()
407
423
  if overlay_view:
408
424
  overlay_view.update_overlay(visible, x, y, window_width, window_height, width, height, scaling)
409
425
 
410
426
  def get_overlay_view(self):
411
427
  """Return the overlay widget exposed to tasks, custom tabs, and my_app."""
428
+ if not self.ok_config.get('use_overlay', False):
429
+ return None
412
430
  if self.overlay_window is None:
413
431
  from ok.core.events import communicate
414
432
  from ok.ui.overlay import Win32GdiOverlay
415
- self.overlay_window = Win32GdiOverlay(og.device_manager.hwnd_window)
433
+ self.overlay_window = Win32GdiOverlay(
434
+ og.device_manager.hwnd_window, exit_event=self.exit_event)
416
435
  communicate.window.connect(self.overlay_window.update_overlay)
417
436
  self.overlay_window.set_boxes_enabled(self.ok_config.get('use_overlay', False))
418
437
  return self.overlay_window
@@ -462,7 +481,14 @@ class App(_OverlayConfigMixin):
462
481
  self.timer.start(1000)
463
482
  self.timer.timeout.connect(lambda: None)
464
483
 
465
- sys.exit(self.app.exec())
484
+ exit_code = self.app.exec()
485
+ # QApplication has stopped, but a forgotten non-daemon worker can
486
+ # still keep the packaged process alive indefinitely. Normal cleanup
487
+ # gets a grace period; the daemon watchdog disappears by itself when
488
+ # Python exits normally.
489
+ from ok.util.process import start_exit_watchdog
490
+ start_exit_watchdog(exit_code=exit_code)
491
+ sys.exit(exit_code)
466
492
 
467
493
 
468
494
  class HeadlessApp(_OverlayConfigMixin):
@@ -536,10 +562,9 @@ class HeadlessApp(_OverlayConfigMixin):
536
562
  communicate.notification.disconnect(self.show_notification)
537
563
  if self.notification_manager is not None:
538
564
  self.notification_manager.stop()
539
- if self.overlay_window is not None:
540
- self.overlay_window.close()
541
565
  if self.exit_event:
542
566
  self.exit_event.set()
567
+ self._close_overlay(wait=False)
543
568
 
544
569
  def show_notification(self, message, title=None, error=False, tray=False,
545
570
  _show_tab=None, params=None, images=None):
@@ -554,11 +579,13 @@ class HeadlessApp(_OverlayConfigMixin):
554
579
  self.notification_manager.submit(translated_title, translated_message, images)
555
580
 
556
581
  def get_overlay_view(self):
582
+ if not self.ok_config.get('use_overlay', False):
583
+ return None
557
584
  if self.overlay_window is None:
558
585
  from ok.core.events import communicate
559
586
  from ok.ui.overlay import Win32GdiOverlay
560
587
  hwnd_window = getattr(getattr(og, 'device_manager', None), 'hwnd_window', None)
561
- self.overlay_window = Win32GdiOverlay(hwnd_window)
588
+ self.overlay_window = Win32GdiOverlay(hwnd_window, exit_event=self.exit_event)
562
589
  communicate.window.connect(self.overlay_window.update_overlay)
563
590
  self.overlay_window.set_boxes_enabled(self.ok_config.get('use_overlay', False))
564
591
  return self.overlay_window
@@ -624,7 +651,9 @@ class OK:
624
651
  wgc_available = _resolve('windows_graphics_available')
625
652
 
626
653
  if config.get('check_mutex', True):
627
- check_mutex_fn()
654
+ if not check_mutex_fn():
655
+ raise RuntimeError(
656
+ 'Another application instance is still running and could not be stopped safely.')
628
657
  og.ok = self
629
658
  if pyappify.app_version:
630
659
  config['version'] = pyappify.app_version
@@ -34,6 +34,7 @@ class WindowsGraphicsCaptureMethod(BaseWindowsCaptureMethod):
34
34
  self.get_frame_lock = threading.RLock()
35
35
  self.frame_event = threading.Event()
36
36
  self.frame_requested = threading.Event()
37
+ self._frame_cancel_generation = 0
37
38
  self.last_frame_time = time.time()
38
39
  self.exit_event = hwnd_window.app_exit_event
39
40
  self.cputex = None
@@ -257,6 +258,12 @@ class WindowsGraphicsCaptureMethod(BaseWindowsCaptureMethod):
257
258
  # _do_get_frame() composites child windows with BitBlt after receiving
258
259
  # the WGC frame. Serialize close with that whole request so its GDI
259
260
  # contexts cannot be released while composite_hwnds() is using them.
261
+ # Wake a pending request before waiting for get_frame_lock; otherwise
262
+ # the GUI close path can wait for the full frame timeout.
263
+ with self.lock:
264
+ self._frame_cancel_generation += 1
265
+ self.frame_requested.clear()
266
+ self.frame_event.set()
260
267
  with self.get_frame_lock:
261
268
  with self.lock:
262
269
  logger.info('destroy windows capture')
@@ -294,7 +301,8 @@ class WindowsGraphicsCaptureMethod(BaseWindowsCaptureMethod):
294
301
  return self._do_get_frame()
295
302
 
296
303
  def _do_get_frame(self):
297
-
304
+ if self.exit_event.is_set():
305
+ return None
298
306
  if self.start_or_stop():
299
307
  now = time.time()
300
308
  if now - self.last_frame_time > 10:
@@ -308,12 +316,21 @@ class WindowsGraphicsCaptureMethod(BaseWindowsCaptureMethod):
308
316
  # consuming such a frame.
309
317
  with self.lock:
310
318
  frame = None
319
+ cancel_generation = self._frame_cancel_generation
311
320
  self.last_frame = None
312
321
  self.frame_event.clear()
313
322
  self.frame_requested.set()
314
323
 
315
324
  deadline = time.monotonic() + WGC_FRAME_WAIT_TIMEOUT
316
325
  while frame is None:
326
+ if self.exit_event.is_set():
327
+ with self.lock:
328
+ self.last_frame = None
329
+ self.frame_requested.clear()
330
+ self.frame_event.clear()
331
+ return None
332
+ if cancel_generation != self._frame_cancel_generation:
333
+ return None
317
334
  timeout_duration = deadline - time.monotonic()
318
335
  if timeout_duration <= 0:
319
336
  # Serialize cancellation with frame_arrived_callback(). If
@@ -328,7 +345,9 @@ class WindowsGraphicsCaptureMethod(BaseWindowsCaptureMethod):
328
345
  self.frame_requested.clear()
329
346
  break
330
347
 
331
- self.frame_event.wait(timeout_duration)
348
+ # ExitEvent cannot directly wake threading.Event, so sample it
349
+ # at a short interval rather than blocking shutdown for 4 s.
350
+ self.frame_event.wait(min(timeout_duration, .05))
332
351
 
333
352
  with self.lock:
334
353
  if self.frame_pool is None:
@@ -89,6 +89,8 @@ class TaskExecutor:
89
89
  self.lock = threading.Lock()
90
90
  self._wake_condition = threading.Condition()
91
91
  self._wake_version = 0
92
+ self._destroy_lock = threading.Lock()
93
+ self._destroyed = False
92
94
  if hasattr(self.exit_event, 'bind_condition'):
93
95
  self.exit_event.bind_condition(self._wake_condition)
94
96
  self._ocr_lib_lock = threading.Lock()
@@ -393,7 +395,10 @@ class TaskExecutor:
393
395
  def start(self):
394
396
  with self.lock:
395
397
  if self.thread is None:
396
- self.thread = threading.Thread(target=self.execute, name="TaskExecutor")
398
+ # Application shutdown must not be held hostage by a custom
399
+ # task or interaction backend that ignores exit_event.
400
+ self.thread = threading.Thread(
401
+ target=self.execute, name="TaskExecutor", daemon=True)
397
402
  self.thread.start()
398
403
  if self.paused:
399
404
  self.paused = False
@@ -623,15 +628,34 @@ class TaskExecutor:
623
628
  self._wake_executor()
624
629
 
625
630
  def destroy(self):
631
+ lock = getattr(self, '_destroy_lock', None)
632
+ if lock is None:
633
+ lock = self._destroy_lock = threading.Lock()
634
+ with lock:
635
+ if getattr(self, '_destroyed', False):
636
+ return
637
+ self._destroyed = True
626
638
  logger.info(f'Executor destroy')
627
- for task in self.onetime_tasks:
628
- task.on_destroy()
629
- self.onetime_tasks = []
630
- for task in self.trigger_tasks:
631
- task.on_destroy()
632
- self.trigger_tasks = []
639
+ onetime_tasks, self.onetime_tasks = self.onetime_tasks, []
640
+ trigger_tasks, self.trigger_tasks = self.trigger_tasks, []
641
+ for task in (*onetime_tasks, *trigger_tasks):
642
+ try:
643
+ task.on_destroy()
644
+ except Exception as error:
645
+ logger.error(f'task on_destroy failed for {task}: {error}')
633
646
  if self.interaction:
634
- self.interaction.on_destroy()
647
+ try:
648
+ self.interaction.on_destroy()
649
+ except Exception as error:
650
+ logger.error(f'interaction on_destroy failed: {error}')
651
+
652
+ def request_destroy(self):
653
+ """Run cleanup away from the GUI close event when needed."""
654
+ if self.thread is not None and self.thread.is_alive():
655
+ # execute() owns normal cleanup after observing exit_event.
656
+ return
657
+ threading.Thread(
658
+ target=self.destroy, name="TaskExecutorCleanup", daemon=True).start()
635
659
 
636
660
  def wait_until_done(self):
637
661
  self.thread.join()