ok-script 0.0.42__tar.gz → 0.0.44__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-0.0.42 → ok-script-0.0.44}/PKG-INFO +11 -9
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/OK.py +2 -2
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/BaseCaptureMethod.py +18 -1
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/HwndWindow.py +33 -50
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/adb/ADBCaptureMethod.py +5 -17
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/adb/DeviceManager.py +89 -48
- ok-script-0.0.44/ok/capture/adb/WindowsCaptureFactory.py +39 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/adb/vbox.py +0 -18
- ok-script-0.0.44/ok/capture/windows/BaseWindowsCaptureMethod.py +36 -0
- ok-script-0.0.44/ok/capture/windows/BitBltCaptureMethod.py +97 -0
- ok-script-0.0.44/ok/capture/windows/DesktopDuplicationCaptureMethod.py +64 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +52 -46
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/windows/window.py +6 -6
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/config/Config.py +1 -1
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/overlay/OverlayWindow.py +1 -1
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/resources.py +394 -358
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/start/StartCard.py +64 -7
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/start/StartTab.py +2 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/logging/Logger.py +6 -4
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/task/TaskExecutor.py +1 -1
- {ok-script-0.0.42 → ok-script-0.0.44}/ok_script.egg-info/PKG-INFO +11 -9
- {ok-script-0.0.42 → ok-script-0.0.44}/ok_script.egg-info/SOURCES.txt +4 -0
- ok-script-0.0.44/ok_script.egg-info/requires.txt +10 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/setup.py +11 -9
- ok-script-0.0.42/ok_script.egg-info/requires.txt +0 -8
- {ok-script-0.0.42 → ok-script-0.0.44}/README.md +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/adb/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/adb/bin/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/adb/targets.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/windows/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/windows/d3d11.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/windows/dump.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/capture/windows/utils.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/color/Color.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/color/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/config/InfoDict.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/config/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/feature/Box.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/feature/Feature.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/feature/FeatureSet.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/feature/FindFeature.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/feature/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/App.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/Communicate.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/MainWindow.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/MessageWindow.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/TabTitles.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/about/AboutTab.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/about/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/common/OKIcon.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/common/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/common/config.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/common/style_sheet.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/debug/AspectRatioWidget.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/debug/DebugTab.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/debug/FrameWidget.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/debug/InfoWidget.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/debug/LoggerWidget.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/debug/Screenshot.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/debug/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/i18n/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/i18n/path.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/i18n/update.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/icon/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/icon/icon.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/overlay/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/qss/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/settings/SettingTab.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/settings/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/start/SelectCaptureListView.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/start/SelectHwndWindow.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/start/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/ConfigItemFactory.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/ConfigLabelAndWidget.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/LabelAndDoubleSpinBox.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/LabelAndDropDown.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/LabelAndLineEdit.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/LabelAndList.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/LabelAndSpinBox.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/LabelAndSwitchButton.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/LabelAndWidget.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/ModifyListDialog.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/ModifyListItem.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/OneTimeTaskTab.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/StartButton.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/TaskCard.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/TaskOpButton.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/TooltipTableWidget.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/TriggerTaskTab.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/tasks/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/util/Alert.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/util/InitWorker.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/util/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/widget/Card.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/widget/FramelessDialog.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/widget/ListTableWidgetItem.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/widget/StatusBar.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/widget/Tab.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/widget/TabWidget.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/widget/YesNonWidgetItem.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/gui/widget/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/interaction/ADBInteraction.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/interaction/BaseInteraction.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/interaction/Win32Interaction.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/interaction/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/logging/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/ocr/OCR.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/ocr/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Media/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Security/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/Storage/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/Windows/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/delegate.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/export.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/idldsl.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/inspectable.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/roapi.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/types.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/rotypes/winstring.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/save/BlackBarProcessor.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/save/PostProcessor.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/save/SaveByInterval.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/save/SaveByKeyPress.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/save/SaveMethodBase.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/save/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/scene/FeatureScene.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/scene/Scene.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/scene/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/stats/StreamStats.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/stats/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/task/BaseTask.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/task/ExecutorOperation.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/task/OneTimeTask.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/task/TriggerTask.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/task/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/util/__init__.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/util/exit_event.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/util/json.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/util/list.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/util/path.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/util/thread.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/util/win32_process.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok/util/yaml.py +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok_script.egg-info/dependency_links.txt +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/ok_script.egg-info/top_level.txt +0 -0
- {ok-script-0.0.42 → ok-script-0.0.44}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ok-script
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.44
|
|
4
4
|
Summary: Automation with Computer Vision for Python
|
|
5
5
|
Home-page: https://github.com/ok-oldking/ok-script
|
|
6
6
|
Author: ok-oldking
|
|
@@ -11,14 +11,16 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
11
11
|
Classifier: Operating System :: Microsoft :: Windows
|
|
12
12
|
Requires-Python: >=3.6
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
|
-
Requires-Dist: adbutils
|
|
15
|
-
Requires-Dist: numpy
|
|
16
|
-
Requires-Dist: PyDirectInput
|
|
17
|
-
Requires-Dist: pywin32
|
|
18
|
-
Requires-Dist: typing-extensions
|
|
19
|
-
Requires-Dist: PySide6
|
|
20
|
-
Requires-Dist: PySide6-Fluent-Widgets
|
|
21
|
-
Requires-Dist:
|
|
14
|
+
Requires-Dist: adbutils>=2.7.2
|
|
15
|
+
Requires-Dist: numpy>=1.26.4
|
|
16
|
+
Requires-Dist: PyDirectInput>=1.0.4
|
|
17
|
+
Requires-Dist: pywin32>=306
|
|
18
|
+
Requires-Dist: typing-extensions>=4.11.0
|
|
19
|
+
Requires-Dist: PySide6>=6.7.0
|
|
20
|
+
Requires-Dist: PySide6-Fluent-Widgets>=1.5.6
|
|
21
|
+
Requires-Dist: psutil>=5.9.8
|
|
22
|
+
Requires-Dist: opencv-python>=4.9.0.80
|
|
23
|
+
Requires-Dist: ok-d3dshot>=0.1.5
|
|
22
24
|
|
|
23
25
|
# ok-script
|
|
24
26
|
|
|
@@ -132,8 +132,8 @@ class OK:
|
|
|
132
132
|
if self.device_manager is None:
|
|
133
133
|
from ok.capture.adb.DeviceManager import DeviceManager
|
|
134
134
|
self.device_manager = DeviceManager(self.config.get("config_folder") or "config",
|
|
135
|
-
self.config.get('
|
|
136
|
-
self.config.get('
|
|
135
|
+
self.config.get('windows_capture'),
|
|
136
|
+
self.config.get('adb_capture'),
|
|
137
137
|
self.config.get("debug"),
|
|
138
138
|
self.exit_event)
|
|
139
139
|
ok.gui.device_manager = self.device_manager
|
|
@@ -18,9 +18,26 @@ class BaseCaptureMethod:
|
|
|
18
18
|
# Some capture methods don't need an initialization process
|
|
19
19
|
pass
|
|
20
20
|
|
|
21
|
+
@property
|
|
22
|
+
def width(self):
|
|
23
|
+
if self._size[0] == 0:
|
|
24
|
+
self.get_frame()
|
|
25
|
+
return self._size[0]
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def height(self):
|
|
29
|
+
if self._size[1] == 0:
|
|
30
|
+
self.get_frame()
|
|
31
|
+
return self._size[1]
|
|
32
|
+
|
|
21
33
|
def get_frame(self) -> np.ndarray | None:
|
|
22
34
|
try:
|
|
23
|
-
|
|
35
|
+
frame = self.do_get_frame()
|
|
36
|
+
if frame is not None:
|
|
37
|
+
self._size = (frame.shape[1], frame.shape[0])
|
|
38
|
+
if frame.shape[2] == 4:
|
|
39
|
+
frame = frame[:, :, :3]
|
|
40
|
+
return frame
|
|
24
41
|
except Exception as e:
|
|
25
42
|
raise CaptureException() from e
|
|
26
43
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# original https://github.com/dantmnf & https://github.com/hakaboom/winAuto
|
|
2
|
-
import ctypes
|
|
3
|
-
import os
|
|
4
2
|
import re
|
|
5
3
|
import threading
|
|
6
4
|
import time
|
|
7
5
|
|
|
6
|
+
import psutil
|
|
8
7
|
import win32process
|
|
9
8
|
from win32 import win32gui
|
|
10
9
|
|
|
@@ -28,6 +27,8 @@ class HwndWindow:
|
|
|
28
27
|
right_cut = 0
|
|
29
28
|
bottom_cut = 0
|
|
30
29
|
left_cut = 0
|
|
30
|
+
ext_left_bounds = 0 # for BitBlt
|
|
31
|
+
ext_top_bounds = 0 # for BitBlt
|
|
31
32
|
window_change_listeners = []
|
|
32
33
|
frame_aspect_ratio = 0
|
|
33
34
|
hwnd = None
|
|
@@ -35,13 +36,14 @@ class HwndWindow:
|
|
|
35
36
|
frame_height = 0
|
|
36
37
|
exists = False
|
|
37
38
|
title = None
|
|
39
|
+
exe_full_path = None
|
|
38
40
|
|
|
39
|
-
def __init__(self, exit_event, title
|
|
41
|
+
def __init__(self, exit_event, title, exe_name=None, frame_width=0, frame_height=0):
|
|
40
42
|
super().__init__()
|
|
41
43
|
self.app_exit_event = exit_event
|
|
42
44
|
self.exe_name = exe_name
|
|
45
|
+
self.title = title
|
|
43
46
|
self.stop_event = threading.Event()
|
|
44
|
-
self.update_title_re(title)
|
|
45
47
|
self.visible = False
|
|
46
48
|
self.update_frame_size(frame_width, frame_height)
|
|
47
49
|
self.do_update_window_size()
|
|
@@ -49,7 +51,7 @@ class HwndWindow:
|
|
|
49
51
|
self.thread.start()
|
|
50
52
|
|
|
51
53
|
def update_title_and_exe(self, title, exe):
|
|
52
|
-
self.
|
|
54
|
+
self.title = title
|
|
53
55
|
self.exe_name = exe
|
|
54
56
|
self.hwnd = None
|
|
55
57
|
self.visible = False
|
|
@@ -61,12 +63,6 @@ class HwndWindow:
|
|
|
61
63
|
def stop(self):
|
|
62
64
|
self.stop_event.set()
|
|
63
65
|
|
|
64
|
-
def update_title_re(self, title):
|
|
65
|
-
if not title:
|
|
66
|
-
self.title = None
|
|
67
|
-
else:
|
|
68
|
-
self.title = re.compile(title)
|
|
69
|
-
|
|
70
66
|
def update_frame_size(self, width, height):
|
|
71
67
|
logger.debug(f"update_frame_size:{self.frame_width}x{self.frame_height} to {width}x{height}")
|
|
72
68
|
if width != self.frame_width or height != self.frame_height:
|
|
@@ -82,24 +78,22 @@ class HwndWindow:
|
|
|
82
78
|
time.sleep(0.2)
|
|
83
79
|
|
|
84
80
|
def get_abs_cords(self, x, y):
|
|
85
|
-
return
|
|
86
|
-
self.y * self.scaling + (y + self.title_height * self.scaling))
|
|
81
|
+
return self.x + self.border + x, self.y + y + self.title_height
|
|
87
82
|
|
|
88
83
|
def get_top_left_frame_offset(self):
|
|
89
|
-
return
|
|
90
|
-
self.title_height * self.scaling)
|
|
84
|
+
return self.border, self.title_height
|
|
91
85
|
|
|
92
86
|
def do_update_window_size(self):
|
|
93
87
|
try:
|
|
94
|
-
visible, x, y, border, title_height, width, height, scaling = self.visible, self.x, self.y, self.border, self.title_height, self.width, self.height, self.scaling
|
|
88
|
+
visible, x, y, border, title_height, width, height, scaling, ext_left_bounds, ext_top_bounds = self.visible, self.x, self.y, self.border, self.title_height, self.width, self.height, self.scaling, self.ext_left_bounds, self.ext_top_bounds
|
|
95
89
|
if self.hwnd is None:
|
|
96
|
-
self.hwnd = find_hwnd_by_title_and_exe(self.title, self.exe_name)
|
|
90
|
+
self.hwnd, self.exe_full_path = find_hwnd_by_title_and_exe(self.title, self.exe_name)
|
|
97
91
|
self.exists = self.hwnd is not None
|
|
98
92
|
if self.hwnd is not None:
|
|
99
93
|
self.exists = win32gui.IsWindow(self.hwnd)
|
|
100
94
|
if self.exists:
|
|
101
95
|
visible = is_foreground_window(self.hwnd)
|
|
102
|
-
x, y, border, title_height, width, height, scaling = get_window_bounds(
|
|
96
|
+
x, y, border, title_height, width, height, scaling, ext_left_bounds, ext_top_bounds = get_window_bounds(
|
|
103
97
|
self.hwnd)
|
|
104
98
|
if self.frame_aspect_ratio != 0 and height != 0:
|
|
105
99
|
window_ratio = width / height
|
|
@@ -117,10 +111,10 @@ class HwndWindow:
|
|
|
117
111
|
self.visible = visible
|
|
118
112
|
self.scaling = scaling
|
|
119
113
|
changed = True
|
|
120
|
-
if (
|
|
121
|
-
|
|
122
|
-
(x >=
|
|
123
|
-
self.x, self.y, self.border, self.title_height, self.width, self.height = x, y, border, title_height, width, height
|
|
114
|
+
if (ext_left_bounds != self.ext_left_bounds or ext_top_bounds != self.ext_top_bounds or
|
|
115
|
+
x != self.x or y != self.y or border != self.border or title_height != self.title_height or width != self.width or height != self.height or scaling != self.scaling) and (
|
|
116
|
+
(x >= -1 and y >= -1) or self.visible):
|
|
117
|
+
self.x, self.y, self.border, self.title_height, self.width, self.height, self.ext_left_bounds, self.ext_top_bounds = x, y, border, title_height, width, height, ext_left_bounds, ext_top_bounds
|
|
124
118
|
changed = True
|
|
125
119
|
if changed:
|
|
126
120
|
logger.debug(
|
|
@@ -141,9 +135,14 @@ class HwndWindow:
|
|
|
141
135
|
return win32gui.GetWindowText(self.hwnd)
|
|
142
136
|
return ""
|
|
143
137
|
|
|
138
|
+
def __str__(self) -> str:
|
|
139
|
+
return f"title:{self.title},exe:{self.exe_name},width:{self.width},height:{self.height},exists:{self.exists},visible:{self.visible}"
|
|
140
|
+
|
|
144
141
|
|
|
145
142
|
def find_hwnd_by_title_and_exe(title, exe_name):
|
|
146
143
|
result = []
|
|
144
|
+
if title is None and exe_name is None:
|
|
145
|
+
return None, None
|
|
147
146
|
|
|
148
147
|
def callback(hwnd, lParam):
|
|
149
148
|
if len(result) == 0 and win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd):
|
|
@@ -154,42 +153,26 @@ def find_hwnd_by_title_and_exe(title, exe_name):
|
|
|
154
153
|
return True
|
|
155
154
|
elif not re.search(title, text):
|
|
156
155
|
return True
|
|
156
|
+
name, full_path = get_exe_by_hwnd(hwnd)
|
|
157
157
|
if exe_name:
|
|
158
|
-
name = get_exe_name_by_hwnd(hwnd)
|
|
159
158
|
if name == exe_name:
|
|
160
|
-
result.append(hwnd)
|
|
159
|
+
result.append((hwnd, full_path))
|
|
161
160
|
return True # Stop enumeration as we found the first match
|
|
162
161
|
else:
|
|
163
|
-
result.append(hwnd)
|
|
162
|
+
result.append((hwnd, full_path))
|
|
164
163
|
return True
|
|
165
164
|
|
|
166
165
|
win32gui.EnumWindows(callback, None)
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
CloseHandle = ctypes.windll.kernel32.CloseHandle
|
|
172
|
-
GetModuleFileNameExW = ctypes.windll.psapi.GetModuleFileNameExW
|
|
166
|
+
if result:
|
|
167
|
+
return result[0][0], result[0][1]
|
|
168
|
+
else:
|
|
169
|
+
return None, None
|
|
173
170
|
|
|
174
|
-
PROCESS_QUERY_INFORMATION = 0x0400
|
|
175
|
-
PROCESS_VM_READ = 0x0010
|
|
176
171
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
# Get the process ID of the window
|
|
172
|
+
def get_exe_by_hwnd(hwnd):
|
|
173
|
+
# Get the process ID associated with the window
|
|
180
174
|
_, pid = win32process.GetWindowThreadProcessId(hwnd)
|
|
181
175
|
|
|
182
|
-
#
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
# Get the executable name
|
|
186
|
-
exe_name = ctypes.create_unicode_buffer(1024)
|
|
187
|
-
GetModuleFileNameExW(h_process, None, exe_name, 1024)
|
|
188
|
-
|
|
189
|
-
# Extract the executable name from the full path
|
|
190
|
-
exe_only_name = os.path.basename(exe_name.value)
|
|
191
|
-
|
|
192
|
-
# Close the process handle
|
|
193
|
-
CloseHandle(h_process)
|
|
194
|
-
|
|
195
|
-
return exe_only_name
|
|
176
|
+
# Get the process name and executable path
|
|
177
|
+
process = psutil.Process(pid)
|
|
178
|
+
return process.name(), process.exe()
|
|
@@ -19,18 +19,6 @@ class ADBCaptureMethod(BaseCaptureMethod):
|
|
|
19
19
|
self._connected = (width != 0 and height != 0)
|
|
20
20
|
self.device_manager = device_manager
|
|
21
21
|
|
|
22
|
-
@property
|
|
23
|
-
def width(self):
|
|
24
|
-
if self._size[0] == 0:
|
|
25
|
-
self.screencap()
|
|
26
|
-
return self._size[0]
|
|
27
|
-
|
|
28
|
-
@property
|
|
29
|
-
def height(self):
|
|
30
|
-
if self._size[1] == 0:
|
|
31
|
-
self.screencap()
|
|
32
|
-
return self._size[1]
|
|
33
|
-
|
|
34
22
|
@override
|
|
35
23
|
def do_get_frame(self) -> np.ndarray | None:
|
|
36
24
|
return self.screencap()
|
|
@@ -38,11 +26,9 @@ class ADBCaptureMethod(BaseCaptureMethod):
|
|
|
38
26
|
def screencap(self):
|
|
39
27
|
if self.exit_event.is_set():
|
|
40
28
|
return None
|
|
41
|
-
frame = do_screencap(self.device_manager)
|
|
29
|
+
frame = do_screencap(self.device_manager.device)
|
|
42
30
|
if frame is not None:
|
|
43
|
-
height, width, _ = frame.shape
|
|
44
31
|
self._connected = True
|
|
45
|
-
self._size = (width, height)
|
|
46
32
|
else:
|
|
47
33
|
self._connected = False
|
|
48
34
|
return frame
|
|
@@ -53,8 +39,10 @@ class ADBCaptureMethod(BaseCaptureMethod):
|
|
|
53
39
|
return self._connected and self.device_manager.device is not None
|
|
54
40
|
|
|
55
41
|
|
|
56
|
-
def do_screencap(
|
|
57
|
-
|
|
42
|
+
def do_screencap(device) -> np.ndarray | None:
|
|
43
|
+
if device is None:
|
|
44
|
+
return None
|
|
45
|
+
png_bytes = device.shell("screencap -p", encoding=None)
|
|
58
46
|
if png_bytes is not None and len(png_bytes) > 0:
|
|
59
47
|
image_data = np.frombuffer(png_bytes, dtype=np.uint8)
|
|
60
48
|
image = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import threading
|
|
2
2
|
|
|
3
|
-
import adbutils
|
|
4
3
|
import win32gui
|
|
5
4
|
from adbutils import AdbError
|
|
6
5
|
|
|
7
6
|
from ok.capture.HwndWindow import HwndWindow, find_hwnd_by_title_and_exe
|
|
8
7
|
from ok.capture.adb.ADBCaptureMethod import ADBCaptureMethod, do_screencap
|
|
8
|
+
from ok.capture.adb.WindowsCaptureFactory import update_capture_method
|
|
9
9
|
from ok.capture.adb.vbox import installed_emulator
|
|
10
|
-
from ok.capture.windows.WindowsGraphicsCaptureMethod import WindowsGraphicsCaptureMethod
|
|
11
10
|
from ok.capture.windows.window import get_window_bounds
|
|
12
11
|
from ok.config.Config import Config
|
|
13
12
|
from ok.gui.Communicate import communicate
|
|
@@ -20,22 +19,24 @@ logger = get_logger(__name__)
|
|
|
20
19
|
|
|
21
20
|
class DeviceManager:
|
|
22
21
|
|
|
23
|
-
def __init__(self, config_folder,
|
|
22
|
+
def __init__(self, config_folder, windows_capture_config, adb_capture_config, debug=False, exit_event=None):
|
|
24
23
|
self._device = None
|
|
25
24
|
self._connect_all = False
|
|
26
|
-
self.
|
|
27
|
-
|
|
28
|
-
self.
|
|
25
|
+
self._adb = None
|
|
26
|
+
self.windows_capture_config = windows_capture_config
|
|
27
|
+
self.adb_capture_config = adb_capture_config
|
|
29
28
|
self.pc_device = None
|
|
30
|
-
self.exe_name = exe_name
|
|
31
29
|
self.debug = debug
|
|
32
30
|
self.interaction = None
|
|
33
31
|
self.exit_event = exit_event
|
|
34
|
-
if
|
|
35
|
-
self.hwnd = HwndWindow(exit_event,
|
|
36
|
-
|
|
32
|
+
if windows_capture_config is not None:
|
|
33
|
+
self.hwnd = HwndWindow(exit_event, windows_capture_config.get('title'),
|
|
34
|
+
windows_capture_config.get('exe'))
|
|
35
|
+
self.config = Config({"devices": {}, "preferred": "none", "pc_full_path": None}, config_folder,
|
|
36
|
+
"DeviceManager")
|
|
37
37
|
self.thread = None
|
|
38
38
|
self.capture_method = None
|
|
39
|
+
self.update_pc_device()
|
|
39
40
|
self.start()
|
|
40
41
|
|
|
41
42
|
def refresh(self):
|
|
@@ -46,6 +47,8 @@ class DeviceManager:
|
|
|
46
47
|
@property
|
|
47
48
|
def device_dict(self):
|
|
48
49
|
device_dict = self.config.get("devices")
|
|
50
|
+
if device_dict is None:
|
|
51
|
+
device_dict = {}
|
|
49
52
|
if self.pc_device is not None:
|
|
50
53
|
full = {'pc': self.pc_device}
|
|
51
54
|
full.update(device_dict)
|
|
@@ -53,6 +56,14 @@ class DeviceManager:
|
|
|
53
56
|
else:
|
|
54
57
|
return device_dict
|
|
55
58
|
|
|
59
|
+
@property
|
|
60
|
+
def adb(self):
|
|
61
|
+
if self._adb is None:
|
|
62
|
+
import adbutils
|
|
63
|
+
self._adb = adbutils.AdbClient(host="127.0.0.1")
|
|
64
|
+
logger.debug(f'connect adb')
|
|
65
|
+
return self._adb
|
|
66
|
+
|
|
56
67
|
def connect_all(self):
|
|
57
68
|
if not self._connect_all:
|
|
58
69
|
for device in self.device_dict.values():
|
|
@@ -67,49 +78,62 @@ class DeviceManager:
|
|
|
67
78
|
def get_devices(self):
|
|
68
79
|
return list(self.device_dict.values())
|
|
69
80
|
|
|
70
|
-
def
|
|
71
|
-
|
|
72
|
-
if self.hwnd_title:
|
|
81
|
+
def update_pc_device(self):
|
|
82
|
+
if self.windows_capture_config is not None:
|
|
73
83
|
nick = ""
|
|
74
84
|
width = 0
|
|
75
85
|
height = 0
|
|
76
|
-
hwnd = find_hwnd_by_title_and_exe(self.
|
|
86
|
+
hwnd, full_path = find_hwnd_by_title_and_exe(self.windows_capture_config.get('title'),
|
|
87
|
+
self.windows_capture_config.get('exe'))
|
|
77
88
|
if hwnd is not None:
|
|
78
89
|
nick = win32gui.GetWindowText(hwnd)
|
|
79
|
-
_, _, _, _, width, height, _ = get_window_bounds(
|
|
90
|
+
_, _, _, _, width, height, _, _, _ = get_window_bounds(
|
|
80
91
|
hwnd)
|
|
81
92
|
if not nick:
|
|
82
|
-
nick = self.
|
|
93
|
+
nick = self.windows_capture_config.get('exe')
|
|
83
94
|
self.pc_device = {"address": "", "imei": 'pc', "device": "windows",
|
|
84
95
|
"model": "", "nick": nick, "width": width,
|
|
85
96
|
"height": height,
|
|
86
97
|
"hwnd": nick, "capture": "windows",
|
|
87
|
-
"connected": hwnd is not None
|
|
98
|
+
"connected": hwnd is not None,
|
|
99
|
+
"full_path": full_path or self.config.get('pc_full_path')
|
|
88
100
|
}
|
|
101
|
+
if full_path and full_path != self.config.get('pc_full_path'):
|
|
102
|
+
self.config['pc_full_path'] = full_path
|
|
103
|
+
|
|
89
104
|
if width != 0:
|
|
90
105
|
self.pc_device["resolution"] = f"{width}x{height}"
|
|
91
106
|
communicate.adb_devices.emit(False)
|
|
92
107
|
|
|
93
|
-
|
|
108
|
+
def do_refresh(self, fast=False):
|
|
109
|
+
self.update_pc_device()
|
|
110
|
+
|
|
111
|
+
self.refresh_adb_device(fast)
|
|
112
|
+
|
|
113
|
+
if self.exit_event.is_set():
|
|
114
|
+
return
|
|
115
|
+
self.start()
|
|
116
|
+
communicate.adb_devices.emit(True)
|
|
117
|
+
logger.debug(f'refresh {self.device_dict}')
|
|
94
118
|
|
|
95
|
-
|
|
119
|
+
def refresh_adb_device(self, fast):
|
|
120
|
+
if self.adb_capture_config is None:
|
|
121
|
+
return
|
|
122
|
+
if not fast:
|
|
123
|
+
self.connect_all()
|
|
124
|
+
installed_emulators = [] if fast else installed_emulator()
|
|
96
125
|
for device in self.adb.list():
|
|
97
126
|
logger.debug(f'adb.list() {device}')
|
|
98
|
-
|
|
99
127
|
for emulator in installed_emulators:
|
|
100
128
|
logger.debug(f"installed_emulator: {emulator}")
|
|
101
|
-
self.adb.connect(emulator.adb_address)
|
|
102
|
-
|
|
129
|
+
self.adb.connect(emulator.adb_address, timeout=1)
|
|
103
130
|
device_list = self.adb.device_list()
|
|
104
|
-
|
|
105
131
|
device_list = sorted(device_list, key=lambda x: x.serial)
|
|
106
|
-
|
|
107
132
|
adb_connected = []
|
|
108
|
-
|
|
109
133
|
for device in device_list:
|
|
110
134
|
imei = device.shell("settings get secure android_id") or device.shell(
|
|
111
135
|
"service call iphonesubinfo 4") or device.prop.model
|
|
112
|
-
frame = do_screencap(device)
|
|
136
|
+
frame = None if fast else do_screencap(device)
|
|
113
137
|
width, height = 0, 0
|
|
114
138
|
if frame is not None:
|
|
115
139
|
height, width, _ = frame.shape
|
|
@@ -128,23 +152,27 @@ class DeviceManager:
|
|
|
128
152
|
old_hwnd = self.device_dict[imei].get("hwnd")
|
|
129
153
|
self.device_dict[imei] = adb_device
|
|
130
154
|
if old_capture is not None:
|
|
131
|
-
self.
|
|
155
|
+
self.update_device_value(imei, 'capture', old_capture)
|
|
132
156
|
if old_hwnd is not None:
|
|
133
|
-
self.
|
|
157
|
+
self.update_device_value(imei, 'hwnd', old_hwnd)
|
|
134
158
|
else:
|
|
135
|
-
self.
|
|
159
|
+
self.update_device(imei, adb_device)
|
|
136
160
|
adb_connected.append(imei)
|
|
137
161
|
for imei in self.device_dict:
|
|
138
|
-
if
|
|
139
|
-
self.
|
|
140
|
-
|
|
162
|
+
if self.device_dict[imei]['device'] == 'adb':
|
|
163
|
+
self.update_device_value(imei, 'connected', imei in adb_connected)
|
|
141
164
|
self.config.save_file()
|
|
142
165
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
166
|
+
def update_device(self, imei, device=None):
|
|
167
|
+
devices = self.config.get("devices", {})
|
|
168
|
+
devices[imei] = device
|
|
169
|
+
self.config["devices"] = devices
|
|
170
|
+
|
|
171
|
+
def update_device_value(self, imei, key, value):
|
|
172
|
+
devices = self.config.get("devices", {})
|
|
173
|
+
if imei in devices:
|
|
174
|
+
devices[imei][key] = value
|
|
175
|
+
self.config["devices"] = devices
|
|
148
176
|
|
|
149
177
|
def set_preferred_device(self, imei=None):
|
|
150
178
|
logger.debug(f"set_preferred_device {imei}")
|
|
@@ -191,6 +219,16 @@ class DeviceManager:
|
|
|
191
219
|
self.hwnd.update_frame_size(frame_width, frame_height)
|
|
192
220
|
self.hwnd.update_title_and_exe(title, exe)
|
|
193
221
|
|
|
222
|
+
def use_windows_capture(self, override_config=None, require_bg=False):
|
|
223
|
+
if not override_config:
|
|
224
|
+
override_config = self.windows_capture_config
|
|
225
|
+
self.capture_method = update_capture_method(override_config, self.capture_method, self.hwnd,
|
|
226
|
+
require_bg)
|
|
227
|
+
if self.capture_method is None:
|
|
228
|
+
logger.error(f'can find a usable windows capture')
|
|
229
|
+
else:
|
|
230
|
+
logger.info(f'capture method {type(self.capture_method)}')
|
|
231
|
+
|
|
194
232
|
def start(self):
|
|
195
233
|
preferred = self.get_preferred_device()
|
|
196
234
|
if preferred is None:
|
|
@@ -199,14 +237,11 @@ class DeviceManager:
|
|
|
199
237
|
return
|
|
200
238
|
|
|
201
239
|
if preferred['device'] == 'windows':
|
|
202
|
-
self.ensure_hwnd(self.
|
|
203
|
-
|
|
204
|
-
if self.capture_method is not None:
|
|
205
|
-
self.capture_method.close()
|
|
206
|
-
self.capture_method = WindowsGraphicsCaptureMethod(self.hwnd)
|
|
240
|
+
self.ensure_hwnd(self.windows_capture_config.get('title'), self.windows_capture_config.get('exe'))
|
|
241
|
+
self.use_windows_capture()
|
|
207
242
|
if not isinstance(self.interaction, Win32Interaction):
|
|
208
243
|
self.interaction = Win32Interaction(self.capture_method)
|
|
209
|
-
|
|
244
|
+
preferred['connected'] = self.capture_method.connected()
|
|
210
245
|
else:
|
|
211
246
|
self.connect_all()
|
|
212
247
|
for adb_device in self.adb.device_list():
|
|
@@ -218,11 +253,9 @@ class DeviceManager:
|
|
|
218
253
|
height = preferred.get('height', 0)
|
|
219
254
|
if preferred.get('capture') == "windows":
|
|
220
255
|
self.ensure_hwnd(hwnd_name, None, width, height)
|
|
221
|
-
if
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
self.capture_method = WindowsGraphicsCaptureMethod(self.hwnd)
|
|
225
|
-
self.capture_method.hwnd_window = self.hwnd
|
|
256
|
+
if self.hwnd.exe_full_path:
|
|
257
|
+
self.update_device_value(preferred['imei'], 'full_path', self.hwnd.exe_full_path)
|
|
258
|
+
self.use_windows_capture({'can_bit_blt': True}, require_bg=True)
|
|
226
259
|
elif not isinstance(self.capture_method, ADBCaptureMethod):
|
|
227
260
|
if self.capture_method is not None:
|
|
228
261
|
self.capture_method.close()
|
|
@@ -271,3 +304,11 @@ class DeviceManager:
|
|
|
271
304
|
return device.shell(*args, **kwargs)
|
|
272
305
|
else:
|
|
273
306
|
raise Exception('Device is none')
|
|
307
|
+
|
|
308
|
+
def get_exe_path(self, device):
|
|
309
|
+
path = device.get('full_path')
|
|
310
|
+
if device.get('device') == 'windows' and self.windows_capture_config and self.windows_capture_config.get(
|
|
311
|
+
'calculate_pc_exe_path'):
|
|
312
|
+
return self.windows_capture_config.get('calculate_pc_exe_path')(path)
|
|
313
|
+
else:
|
|
314
|
+
return path
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from ok.logging.Logger import get_logger
|
|
2
|
+
|
|
3
|
+
logger = get_logger(__name__)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def update_capture_method(config, capture_method, hwnd, require_bg=False):
|
|
7
|
+
if config.get('can_bit_blt'):
|
|
8
|
+
logger.debug(
|
|
9
|
+
f"try BitBlt method {config} current_type:{type(capture_method)}")
|
|
10
|
+
from ok.capture.windows.BitBltCaptureMethod import BitBltCaptureMethod
|
|
11
|
+
target_method = BitBltCaptureMethod
|
|
12
|
+
capture_method = get_capture(capture_method, target_method, hwnd)
|
|
13
|
+
if capture_method.test_exclusive_full_screen():
|
|
14
|
+
return capture_method
|
|
15
|
+
else:
|
|
16
|
+
logger.info("test_exclusive_full_screen failed, can't use BitBlt")
|
|
17
|
+
from ok.capture.windows.WindowsGraphicsCaptureMethod import windows_graphics_available
|
|
18
|
+
if windows_graphics_available():
|
|
19
|
+
from ok.capture.windows.WindowsGraphicsCaptureMethod import WindowsGraphicsCaptureMethod
|
|
20
|
+
target_method = WindowsGraphicsCaptureMethod
|
|
21
|
+
capture_method = get_capture(capture_method, target_method, hwnd)
|
|
22
|
+
return capture_method
|
|
23
|
+
|
|
24
|
+
if not require_bg:
|
|
25
|
+
from ok.capture.windows.DesktopDuplicationCaptureMethod import DesktopDuplicationCaptureMethod
|
|
26
|
+
target_method = DesktopDuplicationCaptureMethod
|
|
27
|
+
capture_method = get_capture(capture_method, target_method, hwnd)
|
|
28
|
+
return capture_method
|
|
29
|
+
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_capture(capture_method, target_method, hwnd):
|
|
34
|
+
if not isinstance(capture_method, target_method):
|
|
35
|
+
if capture_method is not None:
|
|
36
|
+
capture_method.close()
|
|
37
|
+
capture_method = target_method(hwnd)
|
|
38
|
+
capture_method.hwnd_window = hwnd
|
|
39
|
+
return capture_method
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import winreg
|
|
4
4
|
from dataclasses import dataclass
|
|
5
5
|
|
|
6
|
-
import adbutils
|
|
7
6
|
import win32com.client
|
|
8
7
|
|
|
9
8
|
from ok.capture.adb.targets import ADBControllerTarget
|
|
@@ -122,20 +121,3 @@ def installed_emulator():
|
|
|
122
121
|
except Exception as e:
|
|
123
122
|
logger.error(f'failed to check server :{server} {e}', e)
|
|
124
123
|
return results
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def _main():
|
|
128
|
-
logger.config({'debug': True})
|
|
129
|
-
adb = adbutils.AdbClient(host="127.0.0.1", port=5037)
|
|
130
|
-
for x in installed_emulator():
|
|
131
|
-
logger.debug(f'installed emulators {x}')
|
|
132
|
-
adb.connect(x.adb_address)
|
|
133
|
-
|
|
134
|
-
logger.debug(adb.device_list())
|
|
135
|
-
for device in adb.device_list():
|
|
136
|
-
logger.debug(device.shell('settings get secure android_id'))
|
|
137
|
-
logger.debug(f'{device.info}')
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if __name__ == '__main__':
|
|
141
|
-
_main()
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# original https://github.com/dantmnf & https://github.com/hakaboom/winAuto
|
|
2
|
+
import ctypes.wintypes
|
|
3
|
+
|
|
4
|
+
from ok.capture.BaseCaptureMethod import BaseCaptureMethod
|
|
5
|
+
from ok.capture.HwndWindow import HwndWindow
|
|
6
|
+
from ok.logging.Logger import get_logger
|
|
7
|
+
|
|
8
|
+
PBYTE = ctypes.POINTER(ctypes.c_ubyte)
|
|
9
|
+
WGC_NO_BORDER_MIN_BUILD = 20348
|
|
10
|
+
|
|
11
|
+
logger = get_logger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BaseWindowsCaptureMethod(BaseCaptureMethod):
|
|
15
|
+
_hwnd_window: HwndWindow = None
|
|
16
|
+
|
|
17
|
+
def __init__(self, hwnd_window: HwndWindow):
|
|
18
|
+
super().__init__()
|
|
19
|
+
self._hwnd_window = hwnd_window
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def hwnd_window(self):
|
|
23
|
+
return self._hwnd_window
|
|
24
|
+
|
|
25
|
+
@hwnd_window.setter
|
|
26
|
+
def hwnd_window(self, hwnd_window):
|
|
27
|
+
self._hwnd_window = hwnd_window
|
|
28
|
+
|
|
29
|
+
def connected(self):
|
|
30
|
+
return self.hwnd_window is not None and self.hwnd_window.exists
|
|
31
|
+
|
|
32
|
+
def get_abs_cords(self, x, y):
|
|
33
|
+
return self.hwnd_window.get_abs_cords(x, y)
|
|
34
|
+
|
|
35
|
+
def clickable(self):
|
|
36
|
+
return self.hwnd_window is not None and self.hwnd_window.visible
|