ok-script 2.0.2__tar.gz → 2.0.4__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.
- {ok_script-2.0.2/ok_script.egg-info → ok_script-2.0.4}/PKG-INFO +1 -1
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/__init__.py +53 -24
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/DeviceManager.py +4 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/hwnd_window.py +17 -8
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/windows_graphics.py +21 -2
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/task/TaskExecutor.py +32 -8
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/overlay/win32_gdi.py +364 -64
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/MainWindow.py +29 -4
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/debug/OverlayWidget.py +1 -79
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/events.py +12 -1
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/en_US.qm +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/en_US.ts +0 -24
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/es_ES.qm +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/es_ES.ts +0 -24
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/ja_JP.qm +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/ja_JP.ts +0 -24
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/ko_KR.qm +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/ko_KR.ts +0 -24
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/zh_CN.qm +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/zh_CN.ts +0 -24
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/zh_TW.qm +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/zh_TW.ts +0 -24
- ok_script-2.0.4/ok/ui/qt/resources.py +18978 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/start/StartTab.py +24 -28
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/OneTimeTaskTab.py +1 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/TaskCard.py +10 -1
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/TriggerTaskTab.py +1 -0
- ok_script-2.0.4/ok/ui/web/static/app.js +11 -0
- ok_script-2.0.4/ok/ui/web/static/index.css +1 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/handler.py +65 -18
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/process.py +234 -19
- {ok_script-2.0.2 → ok_script-2.0.4/ok_script.egg-info}/PKG-INFO +1 -1
- {ok_script-2.0.2 → ok_script-2.0.4}/ok_script.egg-info/SOURCES.txt +3 -0
- ok_script-2.0.4/tests/test_handler.py +76 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_main_window_startup_tab.py +9 -1
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_ok_mutex.py +11 -2
- ok_script-2.0.4/tests/test_overlay_custom_draw.py +157 -0
- ok_script-2.0.4/tests/test_process_mutex.py +78 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_qt_events.py +13 -0
- ok_script-2.0.4/tests/test_start_tab_overlay.py +17 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_task_executor_queue.py +14 -1
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_task_ui.py +23 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_web_app.py +61 -3
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_windows_graphics_capture.py +17 -0
- ok_script-2.0.2/ok/ui/qt/resources.py +0 -19337
- ok_script-2.0.2/ok/ui/web/static/app.js +0 -11
- ok_script-2.0.2/ok/ui/web/static/index.css +0 -1
- ok_script-2.0.2/tests/test_overlay_custom_draw.py +0 -61
- {ok_script-2.0.2 → ok_script-2.0.4}/LICENSE.txt +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/MANIFEST.in +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/README.md +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/diagnostics/qq_trace.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/__main__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/alas/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/alas/emulator_base.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/alas/emulator_windows.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/alas/platform_windows.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/alas/utils.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/capture/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/capture/adb/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/capture/adb/deep.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/capture/adb/minitouch.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/capture/adb/nemu_ipc.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/capture/adb/nemu_utils.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/capture/adb/pool.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/capture/adb/timer.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/capture/adb/util.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/capture/windows/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/capture/windows/d3d11.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/capture/windows/dump.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/cli.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/config_schema.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/downloads.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/events.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/icons.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/notifications.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/screenshot.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/script_editing.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/script_packager.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/script_templates.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/start_controller.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/task_manager.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/template_store.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/translation.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/core/ui_config.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/adb.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/base.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/bitblt.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/bitblt_utils.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/browser.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/desktop_duplication.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/image.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/nemu_ipc.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/types.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/capture_methods/update.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction_methods/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction_methods/adb.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction_methods/base.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction_methods/browser.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction_methods/do_nothing.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction_methods/foreground_post_message.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction_methods/genshin.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction_methods/keys.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction_methods/post_message.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction_methods/pydirect.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction_methods/pynput.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/interaction_methods/swipe.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/device/intercation.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/feature/Box.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/feature/Feature.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/feature/FeatureSet.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/feature/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/gui/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/gui/util/pyappify_startup.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/notification/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/notification/manager.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/notification/messenger_images.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/notification/pipeline.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/notification/ppocr.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/notification/providers.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/notification/system.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/notification/windows_messenger.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ocr/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ocr/download_paddle_model.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Media/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Security/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/Storage/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/UI/ViewManagement/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/UI/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/Windows/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/delegate.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/export.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/idldsl.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/inspectable.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/roapi.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/types.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/rotypes/winstring.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/task/DiagnosisTask.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/task/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/task/exceptions.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/task/task.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/task/web.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/test/OKTestRunner.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/test/RunTests.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/test/TaskTestCase.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/test/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/third_party/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/third_party/paperclip.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/overlay/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/Communicate.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/MessageWindow.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/StartController.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/TabTitles.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/about/AboutTab.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/about/HttpTextEdit.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/about/LinksBar.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/about/ProjectCard.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/about/UpdateCard.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/about/VersionCard.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/about/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/common/OKIcon.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/common/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/common/accent_color.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/common/config.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/common/design_system.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/common/icons.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/common/style_sheet.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/debug/DebugTab.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/debug/RunCodeTab.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/debug/Screenshot.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/debug/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/GettextTranslator.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/path.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/i18n/update.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/overlay/OverlayWindow.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/overlay/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/dark/card.qss +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/dark/discord.svg +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/dark/heart.svg +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/dark/message_window.qss +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/dark/setting_interface.qss +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/dark/status_bar.qss +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/dark/stop.svg +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/dark/tab.qss +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/light/card.qss +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/light/discord.svg +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/light/heart.svg +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/light/message_window.qss +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/light/setting_interface.qss +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/light/status_bar.qss +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/light/stop.svg +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qss/light/tab.qss +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/qt.qrc +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/settings/GlobalConfigCard.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/settings/GlobalConfigTab.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/settings/SettingTab.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/settings/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/start/LogWindow.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/start/SelectCaptureListView.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/start/SelectInteractionListView.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/start/StartCard.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/start/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/ConfigCard.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/ConfigItemFactory.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/ConfigLabelAndWidget.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/EditTaskTab.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/LabelAndButtons.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/LabelAndDoubleSpinBox.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/LabelAndDropDown.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/LabelAndFileSelector.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/LabelAndGlobal.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/LabelAndLineEdit.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/LabelAndList.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/LabelAndMultiSelection.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/LabelAndSpinBox.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/LabelAndSwitchButton.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/LabelAndTextEdit.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/LabelAndWidget.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/MarkUpWindow.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/ModifyListDialog.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/ModifyListItem.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/PythonHighlighter.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/RecordScript.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/ScheduleTaskTab.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/ScriptPackager.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/StartButton.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/TaskManger.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/TaskOpButton.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/TaskTab.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/TemplateFactory.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/TemplateTab.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/TooltipTableWidget.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/tasks/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/util/Alert.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/util/InitWorker.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/util/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/util/app.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/util/download.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/util/pip_util.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/util/pyappify_startup.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/util/touch_scroll.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/util/windows_thumbnail.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/BaseLoading.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/BaseWindow.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/Card.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/CustomTab.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/EmptyCard.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/ExpandCardLayout.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/FlowLayout.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/FramelessDialog.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/ImageWidget.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/ListTableWidgetItem.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/NumericTableWidgetItem.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/OkCompactSpinBox.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/SortingTableWidgetItem.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/StartLoadingDialog.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/StatusBar.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/Tab.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/TabWidget.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/UpdateConfigWidgetItem.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/WidgetWithVLabel.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/YesNonWidgetItem.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/qt/widget/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/web/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/web/app.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/web/requirements.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/web/server.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/web/static/chunk-fluent.js +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/web/static/chunk-react.js +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/ui/web/static/index.html +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/update/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/update/copy_ok_folder.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/update/inline_ok_requirements.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/Analytics.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/GlobalConfig.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/__init__.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/blur.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/clazz.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/collection.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/color.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/config.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/explorer.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/file.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/gpu_driver_settings.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/i18n.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/logger.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/partial_sync_repo.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/print_hwnd.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/window.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok/util/windows_schedule.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok_script.egg-info/dependency_links.txt +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok_script.egg-info/entry_points.txt +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok_script.egg-info/not-zip-safe +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok_script.egg-info/requires.txt +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/ok_script.egg-info/top_level.txt +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/pyproject.toml +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/scripts/generate_web_i18n.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/setup.cfg +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/setup.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_accent_color.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_app.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_base_interaction.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_blur.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_box.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_capture_update.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_cli.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_config_card.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_core_events.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_core_ui_services.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_device_manager.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_expand_card_layout.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_explorer.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_global_config.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_gpu_driver_settings.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_headless_imports.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_inline_ok_requirements.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_logger.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_main_window_notifications.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_main_window_system_theme.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_missing_frame.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_navigation_state.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_nemu_ipc_capture.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_notifications.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_package_metadata.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_process.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_pyappify_startup_update.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_qt_legacy_imports.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_qt_page_layout.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_runtime_startup.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_start_controller.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_template_tab.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_touch_scroll.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_translation_fallback.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_ui_config.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_web_i18n.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_web_server.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_web_task_tabs.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_web_ui_pages.py +0 -0
- {ok_script-2.0.2 → ok_script-2.0.4}/tests/test_web_ui_tasks.py +0 -0
|
@@ -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
|
-
|
|
230
|
-
|
|
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)
|
|
239
|
+
if self.ok_config.get('use_overlay', False):
|
|
245
240
|
overlay = self.get_overlay_view()
|
|
246
|
-
overlay
|
|
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
|
-
|
|
258
|
-
if key is None:
|
|
265
|
+
if name != 'boxes':
|
|
259
266
|
raise ValueError(f'Unknown overlay setting: {name}')
|
|
260
267
|
|
|
261
|
-
self.ok_config[
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
@@ -131,6 +131,10 @@ class DeviceManager:
|
|
|
131
131
|
|
|
132
132
|
def close(self):
|
|
133
133
|
"""Stop capture resources before Qt/Python teardown begins."""
|
|
134
|
+
hwnd_window = self.hwnd_window
|
|
135
|
+
if hwnd_window is not None:
|
|
136
|
+
hwnd_window.stop()
|
|
137
|
+
|
|
134
138
|
capture_method = self.capture_method
|
|
135
139
|
self.capture_method = None
|
|
136
140
|
if capture_method is not None:
|
|
@@ -68,7 +68,7 @@ class HwndWindow:
|
|
|
68
68
|
self.global_config = global_config
|
|
69
69
|
self.mute_option.validator = self.validate_mute_config
|
|
70
70
|
self.update_window(title, exe_name, frame_width, frame_height, player_id, hwnd_class, top_hwnd_class)
|
|
71
|
-
self.thread = threading.Thread(target=self.update_window_size, name="update_window_size")
|
|
71
|
+
self.thread = threading.Thread(target=self.update_window_size, name="update_window_size", daemon=True)
|
|
72
72
|
self.thread.start()
|
|
73
73
|
|
|
74
74
|
def validate_mute_config(self, key, value):
|
|
@@ -82,7 +82,13 @@ class HwndWindow:
|
|
|
82
82
|
return True, None
|
|
83
83
|
|
|
84
84
|
def stop(self):
|
|
85
|
-
|
|
85
|
+
try:
|
|
86
|
+
self.stop_event.set()
|
|
87
|
+
window_thread = getattr(self, 'thread', None)
|
|
88
|
+
if window_thread is not None and window_thread is not threading.current_thread():
|
|
89
|
+
window_thread.join(timeout=1)
|
|
90
|
+
except Exception as error:
|
|
91
|
+
logger.error(f'hwnd window close failed: {error}')
|
|
86
92
|
|
|
87
93
|
def _front_hwnd_candidates(self):
|
|
88
94
|
return list(dict.fromkeys(hwnd for hwnd in (self.top_hwnd, self.hwnd) if hwnd))
|
|
@@ -183,12 +189,15 @@ class HwndWindow:
|
|
|
183
189
|
self.do_update_window_size()
|
|
184
190
|
|
|
185
191
|
def update_window_size(self):
|
|
186
|
-
|
|
187
|
-
self.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
+
try:
|
|
193
|
+
while not self.app_exit_event.is_set() and not self.stop_event.is_set():
|
|
194
|
+
self.do_update_window_size()
|
|
195
|
+
time.sleep(0.2)
|
|
196
|
+
if self.hwnd and self.mute_option.get('Mute Game while in Background'):
|
|
197
|
+
logger.info(f'exit reset mute state to 0')
|
|
198
|
+
set_mute_state(self.hwnd, 0)
|
|
199
|
+
except Exception as error:
|
|
200
|
+
logger.error(f'update_window_size exception: {error}')
|
|
192
201
|
|
|
193
202
|
def get_abs_cords(self, x, y):
|
|
194
203
|
return self.x + x, self.y + y
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
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
|
-
|
|
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()
|