VirtualDesktop 1.6.2__tar.gz → 1.6.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/PKG-INFO +2 -2
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/README.md +1 -1
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/__init__.py +1 -1
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop.egg-info/PKG-INFO +2 -2
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/pyproject.toml +1 -1
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_record.py +24 -6
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/LICENSE +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/__main__.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/_bundle.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/_compat.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/_desktop_runtime.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/_devices.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/_download.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/_enumerate.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/_helper.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/_log.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/_process.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/_sigcheck.ps1 +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/_sigcheck.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/_winapi.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/agent.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/capture.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/cli.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/config.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/desktop.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/desktop_capture.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/desktop_session.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/display_setup.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/driver.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/driver_manifest.json +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/errors.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/manifest.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/record.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/session.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/window.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop/workspace.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop.egg-info/SOURCES.txt +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop.egg-info/dependency_links.txt +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop.egg-info/entry_points.txt +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop.egg-info/requires.txt +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/VirtualDesktop.egg-info/top_level.txt +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/setup.cfg +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_accelerators.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_agent.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_artifact_regression.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_capture.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_cli.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_compat.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_config_and_winapi.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_desktop_isolation.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_destructive_lifecycle.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_display_setup.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_download.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_driver.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_hide_modes.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_integration_windows.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_manifest.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_no_dialogs.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_packaging.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_process.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_virtual_desktop.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_workspace.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_workspace_instances.py +0 -0
- {virtualdesktop-1.6.2 → virtualdesktop-1.6.3}/tests/test_workspace_move.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: VirtualDesktop
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.3
|
|
4
4
|
Summary: win10-win11 虚拟桌面
|
|
5
5
|
Author: VirtualDesktop contributors
|
|
6
6
|
License: MIT License
|
|
@@ -677,7 +677,7 @@ VIRTUALDESKTOP_LOG_FILE=<path>
|
|
|
677
677
|
| `capture_desktop()` 报"workspace has no monitor" | `offscreen` 模式没有属于自己的屏幕区域 | 用 `hide_mode="virtual_screen"`,或改用 `capture(hwnd)` / `record_window(hwnd)` |
|
|
678
678
|
| 录制报 `record-would-capture-user-screen` | 工作区用的是物理屏 | 改用虚拟显示器;确实要录主屏请显式传 `monitor="primary"` |
|
|
679
679
|
| 录制报 `ffmpeg-missing` | 目标格式是视频但 PATH 上没有 ffmpeg | 装 ffmpeg、传 `ffmpeg=<路径>`,或改录 `.gif` / 帧序列 |
|
|
680
|
-
|
|
|
680
|
+
| 桌面截图/录制**所有**显示器都报 `desktop-capture-failed`,`BitBlt` 与 `GetPixel` 一起失效 | 桌面设备上下文的像素读取能力整体失效(显示栈状态异常,不是本库也不是驱动残留) | **注销重登或重启系统**即可恢复;窗口截图(`PrintWindow`)不受影响,可继续用 |
|
|
681
681
|
| 真实鼠标点击无效 | 窗口在屏幕之外,或拿不到前台焦点 | 用 `virtual_screen`,或改用消息驱动 |
|
|
682
682
|
|
|
683
683
|
**离线 / 内网部署**:把安装包按清单里的文件名(`VirtualDesktop/driver_manifest.json` 的
|
|
@@ -620,7 +620,7 @@ VIRTUALDESKTOP_LOG_FILE=<path>
|
|
|
620
620
|
| `capture_desktop()` 报"workspace has no monitor" | `offscreen` 模式没有属于自己的屏幕区域 | 用 `hide_mode="virtual_screen"`,或改用 `capture(hwnd)` / `record_window(hwnd)` |
|
|
621
621
|
| 录制报 `record-would-capture-user-screen` | 工作区用的是物理屏 | 改用虚拟显示器;确实要录主屏请显式传 `monitor="primary"` |
|
|
622
622
|
| 录制报 `ffmpeg-missing` | 目标格式是视频但 PATH 上没有 ffmpeg | 装 ffmpeg、传 `ffmpeg=<路径>`,或改录 `.gif` / 帧序列 |
|
|
623
|
-
|
|
|
623
|
+
| 桌面截图/录制**所有**显示器都报 `desktop-capture-failed`,`BitBlt` 与 `GetPixel` 一起失效 | 桌面设备上下文的像素读取能力整体失效(显示栈状态异常,不是本库也不是驱动残留) | **注销重登或重启系统**即可恢复;窗口截图(`PrintWindow`)不受影响,可继续用 |
|
|
624
624
|
| 真实鼠标点击无效 | 窗口在屏幕之外,或拿不到前台焦点 | 用 `virtual_screen`,或改用消息驱动 |
|
|
625
625
|
|
|
626
626
|
**离线 / 内网部署**:把安装包按清单里的文件名(`VirtualDesktop/driver_manifest.json` 的
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: VirtualDesktop
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.3
|
|
4
4
|
Summary: win10-win11 虚拟桌面
|
|
5
5
|
Author: VirtualDesktop contributors
|
|
6
6
|
License: MIT License
|
|
@@ -677,7 +677,7 @@ VIRTUALDESKTOP_LOG_FILE=<path>
|
|
|
677
677
|
| `capture_desktop()` 报"workspace has no monitor" | `offscreen` 模式没有属于自己的屏幕区域 | 用 `hide_mode="virtual_screen"`,或改用 `capture(hwnd)` / `record_window(hwnd)` |
|
|
678
678
|
| 录制报 `record-would-capture-user-screen` | 工作区用的是物理屏 | 改用虚拟显示器;确实要录主屏请显式传 `monitor="primary"` |
|
|
679
679
|
| 录制报 `ffmpeg-missing` | 目标格式是视频但 PATH 上没有 ffmpeg | 装 ffmpeg、传 `ffmpeg=<路径>`,或改录 `.gif` / 帧序列 |
|
|
680
|
-
|
|
|
680
|
+
| 桌面截图/录制**所有**显示器都报 `desktop-capture-failed`,`BitBlt` 与 `GetPixel` 一起失效 | 桌面设备上下文的像素读取能力整体失效(显示栈状态异常,不是本库也不是驱动残留) | **注销重登或重启系统**即可恢复;窗口截图(`PrintWindow`)不受影响,可继续用 |
|
|
681
681
|
| 真实鼠标点击无效 | 窗口在屏幕之外,或拿不到前台焦点 | 用 `virtual_screen`,或改用消息驱动 |
|
|
682
682
|
|
|
683
683
|
**离线 / 内网部署**:把安装包按清单里的文件名(`VirtualDesktop/driver_manifest.json` 的
|
|
@@ -142,6 +142,13 @@ def test_recording_a_window_writes_a_playable_gif(tmp_path):
|
|
|
142
142
|
|
|
143
143
|
|
|
144
144
|
def test_recording_a_window_writes_an_h264_file_when_ffmpeg_exists(tmp_path):
|
|
145
|
+
"""The file must be a real H.264 MP4, finalised before the process exits.
|
|
146
|
+
|
|
147
|
+
The frame count is deliberately *not* pinned to a fraction of ``fps``: the first capture of a
|
|
148
|
+
just-launched window can take seconds on a loaded machine, and a short recording then legitimately
|
|
149
|
+
contains a single frame. What matters here is that the encoder ran, the container is valid, and
|
|
150
|
+
the pipe was closed by the recorder rather than by the interpreter exiting.
|
|
151
|
+
"""
|
|
145
152
|
if not shutil.which("ffmpeg"):
|
|
146
153
|
pytest.skip("ffmpeg is not on PATH")
|
|
147
154
|
target = tmp_path / "win.mp4"
|
|
@@ -153,7 +160,7 @@ def test_recording_a_window_writes_an_h264_file_when_ffmpeg_exists(tmp_path):
|
|
|
153
160
|
|
|
154
161
|
assert report.ok, report.describe()
|
|
155
162
|
assert report.backend == "ffmpeg"
|
|
156
|
-
assert report.frames >=
|
|
163
|
+
assert report.frames >= 1, report.to_dict()
|
|
157
164
|
# Finalised inside the block, so the file is complete before the process exits.
|
|
158
165
|
assert report.bytes_written > 0
|
|
159
166
|
head = target.read_bytes()[:16]
|
|
@@ -550,7 +557,13 @@ def test_desktop_recording_writes_the_workspaces_own_monitor(tmp_path):
|
|
|
550
557
|
assert report.ok, report.describe()
|
|
551
558
|
assert report.target == f"desktop:{monitor.device}"
|
|
552
559
|
# The recording is the monitor's rectangle, not a full-screen sweep.
|
|
553
|
-
assert report.size ==
|
|
560
|
+
assert tuple(report.size) == (monitor.width, monitor.height)
|
|
561
|
+
# And it contains real pixels: a desktop recording of a monitor with a window on it must not be
|
|
562
|
+
# a blank frame.
|
|
563
|
+
from PIL import Image
|
|
564
|
+
|
|
565
|
+
with Image.open(target) as image:
|
|
566
|
+
assert _variance(image) > 20.0, "the recorded desktop looks blank"
|
|
554
567
|
|
|
555
568
|
|
|
556
569
|
@desktop_recording
|
|
@@ -572,7 +585,12 @@ def test_desktop_recording_is_bounded_by_the_monitor_not_the_whole_desktop(tmp_p
|
|
|
572
585
|
from VirtualDesktop._winapi import virtual_screen_rect
|
|
573
586
|
|
|
574
587
|
whole = virtual_screen_rect()
|
|
575
|
-
assert report.size ==
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
588
|
+
assert tuple(report.size) == (monitor.width, monitor.height)
|
|
589
|
+
# The virtual desktop spans every monitor, so a recording of the workspace's own monitor must be
|
|
590
|
+
# narrower than it unless there is only one monitor attached.
|
|
591
|
+
whole_size = (whole[2] - whole[0], whole[3] - whole[1])
|
|
592
|
+
monitors = __import__("VirtualDesktop").enumerate_monitors()
|
|
593
|
+
if len(monitors) > 1:
|
|
594
|
+
assert tuple(report.size) != whole_size, (
|
|
595
|
+
f"recorded {report.size} which is the whole virtual desktop, not the monitor"
|
|
596
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|