ok-script 0.0.43__tar.gz → 0.0.45__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.43 → ok-script-0.0.45}/PKG-INFO +11 -9
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/OK.py +2 -2
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/BaseCaptureMethod.py +18 -1
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/HwndWindow.py +29 -51
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/adb/ADBCaptureMethod.py +5 -17
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/adb/DeviceManager.py +74 -46
- ok-script-0.0.45/ok/capture/adb/WindowsCaptureFactory.py +39 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/adb/vbox.py +0 -18
- ok-script-0.0.45/ok/capture/windows/BaseWindowsCaptureMethod.py +36 -0
- ok-script-0.0.45/ok/capture/windows/BitBltCaptureMethod.py +97 -0
- ok-script-0.0.45/ok/capture/windows/DesktopDuplicationCaptureMethod.py +64 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +45 -41
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/windows/window.py +6 -6
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/config/Config.py +1 -1
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/overlay/OverlayWindow.py +1 -1
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/resources.py +394 -358
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/start/StartCard.py +67 -11
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/start/StartTab.py +2 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/logging/Logger.py +6 -4
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/task/TaskExecutor.py +1 -1
- {ok-script-0.0.43 → ok-script-0.0.45}/ok_script.egg-info/PKG-INFO +11 -9
- {ok-script-0.0.43 → ok-script-0.0.45}/ok_script.egg-info/SOURCES.txt +4 -0
- ok-script-0.0.45/ok_script.egg-info/requires.txt +10 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/setup.py +11 -9
- ok-script-0.0.43/ok_script.egg-info/requires.txt +0 -8
- {ok-script-0.0.43 → ok-script-0.0.45}/README.md +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/adb/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/adb/bin/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/adb/targets.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/windows/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/windows/d3d11.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/windows/dump.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/capture/windows/utils.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/color/Color.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/color/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/config/InfoDict.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/config/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/feature/Box.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/feature/Feature.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/feature/FeatureSet.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/feature/FindFeature.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/feature/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/App.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/Communicate.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/MainWindow.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/MessageWindow.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/TabTitles.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/about/AboutTab.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/about/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/common/OKIcon.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/common/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/common/config.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/common/style_sheet.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/debug/AspectRatioWidget.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/debug/DebugTab.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/debug/FrameWidget.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/debug/InfoWidget.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/debug/LoggerWidget.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/debug/Screenshot.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/debug/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/i18n/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/i18n/path.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/i18n/update.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/icon/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/icon/icon.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/overlay/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/qss/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/settings/SettingTab.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/settings/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/start/SelectCaptureListView.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/start/SelectHwndWindow.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/start/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/ConfigItemFactory.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/ConfigLabelAndWidget.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/LabelAndDoubleSpinBox.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/LabelAndDropDown.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/LabelAndLineEdit.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/LabelAndList.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/LabelAndSpinBox.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/LabelAndSwitchButton.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/LabelAndWidget.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/ModifyListDialog.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/ModifyListItem.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/OneTimeTaskTab.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/StartButton.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/TaskCard.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/TaskOpButton.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/TooltipTableWidget.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/TriggerTaskTab.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/tasks/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/util/Alert.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/util/InitWorker.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/util/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/widget/Card.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/widget/FramelessDialog.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/widget/ListTableWidgetItem.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/widget/StatusBar.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/widget/Tab.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/widget/TabWidget.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/widget/YesNonWidgetItem.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/gui/widget/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/interaction/ADBInteraction.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/interaction/BaseInteraction.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/interaction/Win32Interaction.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/interaction/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/logging/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/ocr/OCR.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/ocr/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Media/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Security/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/Storage/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/Windows/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/delegate.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/export.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/idldsl.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/inspectable.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/roapi.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/types.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/rotypes/winstring.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/save/BlackBarProcessor.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/save/PostProcessor.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/save/SaveByInterval.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/save/SaveByKeyPress.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/save/SaveMethodBase.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/save/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/scene/FeatureScene.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/scene/Scene.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/scene/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/stats/StreamStats.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/stats/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/task/BaseTask.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/task/ExecutorOperation.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/task/OneTimeTask.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/task/TriggerTask.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/task/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/util/__init__.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/util/exit_event.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/util/json.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/util/list.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/util/path.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/util/thread.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/util/win32_process.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok/util/yaml.py +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok_script.egg-info/dependency_links.txt +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/ok_script.egg-info/top_level.txt +0 -0
- {ok-script-0.0.43 → ok-script-0.0.45}/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.45
|
|
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(
|
|
@@ -148,7 +142,7 @@ class HwndWindow:
|
|
|
148
142
|
def find_hwnd_by_title_and_exe(title, exe_name):
|
|
149
143
|
result = []
|
|
150
144
|
if title is None and exe_name is None:
|
|
151
|
-
return None
|
|
145
|
+
return None, None
|
|
152
146
|
|
|
153
147
|
def callback(hwnd, lParam):
|
|
154
148
|
if len(result) == 0 and win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd):
|
|
@@ -159,42 +153,26 @@ def find_hwnd_by_title_and_exe(title, exe_name):
|
|
|
159
153
|
return True
|
|
160
154
|
elif not re.search(title, text):
|
|
161
155
|
return True
|
|
156
|
+
name, full_path = get_exe_by_hwnd(hwnd)
|
|
162
157
|
if exe_name:
|
|
163
|
-
name = get_exe_name_by_hwnd(hwnd)
|
|
164
158
|
if name == exe_name:
|
|
165
|
-
result.append(hwnd)
|
|
159
|
+
result.append((hwnd, full_path))
|
|
166
160
|
return True # Stop enumeration as we found the first match
|
|
167
161
|
else:
|
|
168
|
-
result.append(hwnd)
|
|
162
|
+
result.append((hwnd, full_path))
|
|
169
163
|
return True
|
|
170
164
|
|
|
171
165
|
win32gui.EnumWindows(callback, None)
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
CloseHandle = ctypes.windll.kernel32.CloseHandle
|
|
177
|
-
GetModuleFileNameExW = ctypes.windll.psapi.GetModuleFileNameExW
|
|
166
|
+
if result:
|
|
167
|
+
return result[0][0], result[0][1]
|
|
168
|
+
else:
|
|
169
|
+
return None, None
|
|
178
170
|
|
|
179
|
-
PROCESS_QUERY_INFORMATION = 0x0400
|
|
180
|
-
PROCESS_VM_READ = 0x0010
|
|
181
171
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
# Get the process ID of the window
|
|
172
|
+
def get_exe_by_hwnd(hwnd):
|
|
173
|
+
# Get the process ID associated with the window
|
|
185
174
|
_, pid = win32process.GetWindowThreadProcessId(hwnd)
|
|
186
175
|
|
|
187
|
-
#
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
# Get the executable name
|
|
191
|
-
exe_name = ctypes.create_unicode_buffer(1024)
|
|
192
|
-
GetModuleFileNameExW(h_process, None, exe_name, 1024)
|
|
193
|
-
|
|
194
|
-
# Extract the executable name from the full path
|
|
195
|
-
exe_only_name = os.path.basename(exe_name.value)
|
|
196
|
-
|
|
197
|
-
# Close the process handle
|
|
198
|
-
CloseHandle(h_process)
|
|
199
|
-
|
|
200
|
-
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):
|
|
@@ -55,6 +56,14 @@ class DeviceManager:
|
|
|
55
56
|
else:
|
|
56
57
|
return device_dict
|
|
57
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
|
+
|
|
58
67
|
def connect_all(self):
|
|
59
68
|
if not self._connect_all:
|
|
60
69
|
for device in self.device_dict.values():
|
|
@@ -69,49 +78,62 @@ class DeviceManager:
|
|
|
69
78
|
def get_devices(self):
|
|
70
79
|
return list(self.device_dict.values())
|
|
71
80
|
|
|
72
|
-
def
|
|
73
|
-
|
|
74
|
-
if self.hwnd_title:
|
|
81
|
+
def update_pc_device(self):
|
|
82
|
+
if self.windows_capture_config is not None:
|
|
75
83
|
nick = ""
|
|
76
84
|
width = 0
|
|
77
85
|
height = 0
|
|
78
|
-
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'))
|
|
79
88
|
if hwnd is not None:
|
|
80
89
|
nick = win32gui.GetWindowText(hwnd)
|
|
81
|
-
_, _, _, _, width, height, _ = get_window_bounds(
|
|
90
|
+
_, _, _, _, width, height, _, _, _ = get_window_bounds(
|
|
82
91
|
hwnd)
|
|
83
92
|
if not nick:
|
|
84
|
-
nick = self.
|
|
93
|
+
nick = self.windows_capture_config.get('exe')
|
|
85
94
|
self.pc_device = {"address": "", "imei": 'pc', "device": "windows",
|
|
86
95
|
"model": "", "nick": nick, "width": width,
|
|
87
96
|
"height": height,
|
|
88
97
|
"hwnd": nick, "capture": "windows",
|
|
89
|
-
"connected": hwnd is not None
|
|
98
|
+
"connected": hwnd is not None,
|
|
99
|
+
"full_path": full_path or self.config.get('pc_full_path')
|
|
90
100
|
}
|
|
101
|
+
if full_path and full_path != self.config.get('pc_full_path'):
|
|
102
|
+
self.config['pc_full_path'] = full_path
|
|
103
|
+
|
|
91
104
|
if width != 0:
|
|
92
105
|
self.pc_device["resolution"] = f"{width}x{height}"
|
|
93
106
|
communicate.adb_devices.emit(False)
|
|
94
107
|
|
|
95
|
-
|
|
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}')
|
|
96
118
|
|
|
97
|
-
|
|
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()
|
|
98
125
|
for device in self.adb.list():
|
|
99
126
|
logger.debug(f'adb.list() {device}')
|
|
100
|
-
|
|
101
127
|
for emulator in installed_emulators:
|
|
102
128
|
logger.debug(f"installed_emulator: {emulator}")
|
|
103
|
-
self.adb.connect(emulator.adb_address)
|
|
104
|
-
|
|
129
|
+
self.adb.connect(emulator.adb_address, timeout=1)
|
|
105
130
|
device_list = self.adb.device_list()
|
|
106
|
-
|
|
107
131
|
device_list = sorted(device_list, key=lambda x: x.serial)
|
|
108
|
-
|
|
109
132
|
adb_connected = []
|
|
110
|
-
|
|
111
133
|
for device in device_list:
|
|
112
134
|
imei = device.shell("settings get secure android_id") or device.shell(
|
|
113
135
|
"service call iphonesubinfo 4") or device.prop.model
|
|
114
|
-
frame = do_screencap(device)
|
|
136
|
+
frame = None if fast else do_screencap(device)
|
|
115
137
|
width, height = 0, 0
|
|
116
138
|
if frame is not None:
|
|
117
139
|
height, width, _ = frame.shape
|
|
@@ -137,17 +159,10 @@ class DeviceManager:
|
|
|
137
159
|
self.update_device(imei, adb_device)
|
|
138
160
|
adb_connected.append(imei)
|
|
139
161
|
for imei in self.device_dict:
|
|
140
|
-
if
|
|
141
|
-
self.update_device_value(imei, 'connected',
|
|
142
|
-
|
|
162
|
+
if self.device_dict[imei]['device'] == 'adb':
|
|
163
|
+
self.update_device_value(imei, 'connected', imei in adb_connected)
|
|
143
164
|
self.config.save_file()
|
|
144
165
|
|
|
145
|
-
if self.exit_event.is_set():
|
|
146
|
-
return
|
|
147
|
-
self.start()
|
|
148
|
-
communicate.adb_devices.emit(True)
|
|
149
|
-
logger.debug(f'refresh {self.device_dict}')
|
|
150
|
-
|
|
151
166
|
def update_device(self, imei, device=None):
|
|
152
167
|
devices = self.config.get("devices", {})
|
|
153
168
|
devices[imei] = device
|
|
@@ -204,6 +219,16 @@ class DeviceManager:
|
|
|
204
219
|
self.hwnd.update_frame_size(frame_width, frame_height)
|
|
205
220
|
self.hwnd.update_title_and_exe(title, exe)
|
|
206
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
|
+
|
|
207
232
|
def start(self):
|
|
208
233
|
preferred = self.get_preferred_device()
|
|
209
234
|
if preferred is None:
|
|
@@ -212,14 +237,11 @@ class DeviceManager:
|
|
|
212
237
|
return
|
|
213
238
|
|
|
214
239
|
if preferred['device'] == 'windows':
|
|
215
|
-
self.ensure_hwnd(self.
|
|
216
|
-
|
|
217
|
-
if self.capture_method is not None:
|
|
218
|
-
self.capture_method.close()
|
|
219
|
-
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()
|
|
220
242
|
if not isinstance(self.interaction, Win32Interaction):
|
|
221
243
|
self.interaction = Win32Interaction(self.capture_method)
|
|
222
|
-
|
|
244
|
+
preferred['connected'] = self.capture_method.connected()
|
|
223
245
|
else:
|
|
224
246
|
self.connect_all()
|
|
225
247
|
for adb_device in self.adb.device_list():
|
|
@@ -231,11 +253,9 @@ class DeviceManager:
|
|
|
231
253
|
height = preferred.get('height', 0)
|
|
232
254
|
if preferred.get('capture') == "windows":
|
|
233
255
|
self.ensure_hwnd(hwnd_name, None, width, height)
|
|
234
|
-
if
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
self.capture_method = WindowsGraphicsCaptureMethod(self.hwnd)
|
|
238
|
-
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)
|
|
239
259
|
elif not isinstance(self.capture_method, ADBCaptureMethod):
|
|
240
260
|
if self.capture_method is not None:
|
|
241
261
|
self.capture_method.close()
|
|
@@ -284,3 +304,11 @@ class DeviceManager:
|
|
|
284
304
|
return device.shell(*args, **kwargs)
|
|
285
305
|
else:
|
|
286
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
|