diff --git a/README.md b/README.md index 968d7b70..c8e58e54 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ Linux users, note that LiveSplit Desktop, with additional components, is only av - Only the BitBlt Capture method is supported. Wine [does not support `CreateDirect3D11DeviceFromDXGIDevice`](https://bugs.winehq.org/show_bug.cgi?id=52487) - No Video Capture Device (ie Webcam, OBS Virtual Cam). Wine [does not support DirectShow Device Enumeration](https://gitlab.winehq.org/wine/wine/-/wikis/Hardware#restrictions:~:text=camera) - Requires Wine 10.1+ / Steam Proton 11+ (due to [added `crealf` implementation](https://gitlab.winehq.org/wine/wine/-/releases/wine-10.1#:~:text=crealf)) -- Wine 10.1 to 11.2 must use the `WineCompat` version of the Windows build (same build but without UPX compression) as Wine hadn't [implemented `PssQuerySnapshot`](https://gitlab.winehq.org/wine/wine/-/merge_requests/8779) yet. +- Wine 10.1 to 11.2 must use the `WineCompat` version of the Windows build (same build but without UPX compression) as Wine hadn't [stubbed `PssQuerySnapshot`](https://gitlab.winehq.org/wine/wine/-/merge_requests/8779) yet. - Wine 11.3+ can use the regular Windows build. - Only applications running within the **same wineserver instance** can be recorded. Which means that if you want to record a Steam Game for example, you would need to run AutoSplit through the same Proton version as the target game, targetting the game's Wine prefix. - For steam games, this can be made a lot easier using [`protontricks`](https://protontricks.com/): `protontricks-launch --appid ` @@ -115,7 +115,6 @@ Not a developer? You can still help through the following methods: - Sharing AutoSplit with other speedrunners - Starring the repository Example - Upvoting 👍 the following upstream issues in libraries and tools we use: - - - - - diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 7d284609..7b53e9a4 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -41,16 +41,10 @@ try { if (-not $WineCompat -and -not $IsLinux) { $arguments += '--upx-dir=scripts/.upx' $arguments += @( - # pywin32's DLLs do custom load-time magic (__import_pywin32_system_module__) that - # UPX self-decompression breaks under Wine ("DLL initialisation failed"). - # Native Windows tolerates it, Wine's loader doesn't. Exclude them from compression. + # Wine doesn't export (not even stub) win32api ole32.Co{Get,Set}CancelObject '--upx-exclude=pythoncom*.dll', - '--upx-exclude=pywintypes*.dll', - '--upx-exclude=win32*.pyd', - # win32comext.shell.shell -> shell.pyd (plain name, no win32 prefix) - '--upx-exclude=shell.pyd', - # winrt projection modules hit the same UPX+Wine DLL-init breakage - '--upx-exclude=_winrt*.pyd') + # Wine doesn't export (not even stub) `ADVAPI32.Reg{Open,Delete}KeyTransactedW` + '--upx-exclude=win32api.pyd') } else { # Missing upx executable should be enough, but let's be explicit diff --git a/src/AutoSplit.py b/src/AutoSplit.py index 22fee6cc..ec06596f 100755 --- a/src/AutoSplit.py +++ b/src/AutoSplit.py @@ -17,8 +17,6 @@ if sys.platform == "win32": import ctypes - from win32comext.shell import shell as shell32 - def do_nothing(*_): ... # pyautogui._pyautogui_win.py @@ -1196,15 +1194,18 @@ def main(): # Call to QApplication outside the try-except so we can show error messages app = QApplication(sys.argv) try: # noqa: PLW0717 # We really want to catch everything here - if sys.platform == "win32": - myappid = f"Toufool.AutoSplit.v{AUTOSPLIT_VERSION}" - shell32.SetCurrentProcessExplicitAppUserModelID(myappid) - # Decouple from the executable basename (which varies per build) app.setApplicationName("AutoSplit") app.setApplicationVersion(AUTOSPLIT_VERSION) app.setWindowIcon(QtGui.QIcon(":/resources/icon.ico")) + if sys.platform == "win32": + # Technically not needed since we version the filename now, + # but kept in case users strips down the executable filename + set_aumid = ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID + set_aumid.restype = ctypes.HRESULT # auto-raises OSError on failure + set_aumid(f"Toufool.AutoSplit.v{AUTOSPLIT_VERSION}") + if is_already_open(): error_messages.already_open() if KEYBOARD_GROUPS_ISSUE: diff --git a/src/capture_method/DesktopDuplicationCaptureMethod.py b/src/capture_method/DesktopDuplicationCaptureMethod.py index 874b5a16..25316de4 100644 --- a/src/capture_method/DesktopDuplicationCaptureMethod.py +++ b/src/capture_method/DesktopDuplicationCaptureMethod.py @@ -21,7 +21,8 @@ from AutoSplit import AutoSplit -try: # Test for laptop cross-GPU Desktop Duplication issue +try: + # Test for laptop cross-GPU Desktop Duplication issue (ModuleNotFoundError or COMError) d3dshot.create(capture_output="numpy") except ModuleNotFoundError, COMError: IS_DESKTOP_DUPLICATION_SUPPORTED = False # pyright: ignore[reportConstantRedefinition] diff --git a/src/capture_method/WindowsGraphicsCaptureMethod.py b/src/capture_method/WindowsGraphicsCaptureMethod.py index d65cafc3..afb947d9 100644 --- a/src/capture_method/WindowsGraphicsCaptureMethod.py +++ b/src/capture_method/WindowsGraphicsCaptureMethod.py @@ -15,9 +15,6 @@ from winrt.windows.graphics.capture import Direct3D11CaptureFramePool, GraphicsCaptureSession from winrt.windows.graphics.capture.interop import create_for_window from winrt.windows.graphics.directx import DirectXPixelFormat -from winrt.windows.graphics.directx.direct3d11.interop import ( - create_direct3d11_device_from_dxgi_device, -) from winrt.windows.graphics.imaging import BitmapBufferAccessMode, SoftwareBitmap from capture_method.CaptureMethodBase import CaptureMethodBase @@ -49,6 +46,12 @@ raise IS_WGC_SUPPORTED = False # pyright: ignore[reportConstantRedefinition] +if TYPE_CHECKING or IS_WGC_SUPPORTED: + # This pyd hard-fails to load when the d3d11 export is missing (UPX+Wine) + from winrt.windows.graphics.directx.direct3d11.interop import ( + create_direct3d11_device_from_dxgi_device, + ) + async def convert_d3d_surface_to_software_bitmap(surface: IDirect3DSurface): return await SoftwareBitmap.create_copy_from_surface_async(surface) diff --git a/src/error_messages.py b/src/error_messages.py index e318e286..21a15df3 100644 --- a/src/error_messages.py +++ b/src/error_messages.py @@ -287,7 +287,7 @@ def excepthook( " returned a result with an error set" ): return - # Whithin LiveSplit excepthook needs to use MainWindow's signals to show errors + # Within LiveSplit excepthook needs to use MainWindow's signals to show errors autosplit.show_error_signal.emit(lambda: exception_traceback(exception)) return excepthook