From 3c691b530c674b4958d9185de82e92b2b787d11e Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 16 Apr 2026 11:42:51 +0800 Subject: [PATCH 1/4] Add .NET Core 10 loader. --- winforms/src/toga_winforms/__init__.py | 61 +++++++++++++++++++ .../src/toga_winforms/resources/runtime.json | 15 +++++ 2 files changed, 76 insertions(+) create mode 100644 winforms/src/toga_winforms/resources/runtime.json diff --git a/winforms/src/toga_winforms/__init__.py b/winforms/src/toga_winforms/__init__.py index 53312ecae5..ea45824004 100644 --- a/winforms/src/toga_winforms/__init__.py +++ b/winforms/src/toga_winforms/__init__.py @@ -1,3 +1,58 @@ +import platform +from pathlib import Path + +import clr_loader +from pythonnet import set_runtime + +try: + #################################################################################### + # Toga Winforms requires the use of .NET; either .NET Framework 4.x, or .NET Core. + # + # .NET Framework 4.x is available by default on Windows 10 and 11. However, on + # Windows on ARM64, it is an x86-64 binary, so it can't be used by a native ARM64 + # Python interpreter. + # + # However, it *can* be used if you have an x86-64 Python interpreter - which is what + # you get if you run `py install -3.13` or `py install -3.14`. This will apparently + # change with Python 3.15. + # + # Using .NET Core requires a separate install - but it will be present on a lot + # of systems. + # + # So - try to load .NET Core; if it succeeds, use it. If the load fails, fall back + # to .NET Framework. If we're on ARM64, check to see if the interpreter is running + # in emulation mode. If it is, we're OK; if we're not, stop the interpreter; the + # .NET gives instructions on how to install .NET + #################################################################################### + + # runtime.json defines the .NET version. .NET 10 is the current LTS release. + set_runtime( + clr_loader.get_coreclr( + runtime_config=Path(__file__).parent / "resources/runtime.json" + ) + ) + + # .NET Core load succeeded + _use_dotnet_core = True +except (clr_loader.util.clr_error.ClrError, RuntimeError): + # .NET Core load failed. + if platform.machine() == "ARM64" and "ARM64" in platform.python_compiler(): + # A native ARM64 machine running an ARM64 Python. + # .NET Framework 4.x isn't an option. + raise RuntimeError(""" + +On Windows, Toga requires .NET Core 10. Please visit: + + https://dotnet.microsoft.com/en-us/download/dotnet/10.0 + +and install the .NET Desktop Runtime.""") from None + else: + # Either a native x86_64 machine, or an ARM64 machine with + # and x86_64 Python interpreter in emulation mode. We can + # use .NET Framework 4.x + _use_dotnet_core = False + + import clr import travertino @@ -9,6 +64,12 @@ # Add a reference to the Winforms assembly clr.AddReference("System.Windows.Forms") +# .NET Core requires some other explicit assemblies +if _use_dotnet_core: + clr.AddReference("Microsoft.Win32.SystemEvents") + clr.AddReference("System.Windows.Extensions") + + # Add a reference to the WindowsBase assembly. This is needed to access # System.Windows.Threading.Dispatcher. # diff --git a/winforms/src/toga_winforms/resources/runtime.json b/winforms/src/toga_winforms/resources/runtime.json new file mode 100644 index 0000000000..aa34ea9d40 --- /dev/null +++ b/winforms/src/toga_winforms/resources/runtime.json @@ -0,0 +1,15 @@ +{ + "runtimeOptions": { + "tfm": "net10.0-windows", + "frameworks": [ + { + "name": "Microsoft.NETCore.App", + "version": "10.0.0" + }, + { + "name": "Microsoft.WindowsDesktop.App", + "version": "10.0.0" + } + ] + } +} From 6545233e9c450d1e3865fcd6d2f14392d8dbfb52 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 16 Apr 2026 11:43:25 +0800 Subject: [PATCH 2/4] Add ARM64 CI jobs on Windows. --- .github/workflows/ci.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c60cad739a..ce7104cd82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -251,7 +251,8 @@ jobs: backend: - "macOS-x86_64" - "macOS-arm64" - - "windows" + - "windows-x86_64" + - "windows-arm64" - "linux-x11-gtk3" - "linux-wayland-gtk3" - "linux-wayland-gtk4" @@ -489,11 +490,16 @@ jobs: briefcase-run-args: --config 'requires=["toga-core", "toga-textual"]' --config 'console_app=true' app-user-data-path: '$HOME\AppData\Local\Tiberius Yak\Toga Testbed\Data' - - backend: "windows" + - backend: "windows-x86_64" platform: "windows" runs-on: "windows-latest" app-user-data-path: '$HOME\AppData\Local\Tiberius Yak\Toga Testbed\Data' + - backend: "windows-arm64" + platform: "windows" + runs-on: "windows-11-arm" + app-user-data-path: '$HOME\AppData\Local\Tiberius Yak\Toga Testbed\Data' + - backend: "iOS" platform: "iOS" runs-on: "macos-latest" From 7f89203496a1619ede8d87061bf2e89d0400112a Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 16 Apr 2026 11:45:13 +0800 Subject: [PATCH 3/4] Document .NET requirements for the Winforms backend. --- docs/en/reference/platforms/windows.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/en/reference/platforms/windows.md b/docs/en/reference/platforms/windows.md index 1f38096b2f..14f6e9eba2 100644 --- a/docs/en/reference/platforms/windows.md +++ b/docs/en/reference/platforms/windows.md @@ -8,11 +8,13 @@ The Toga backend for Windows is [`toga-winforms`](https://github.com/beeware/tog `toga-winforms` requires Python 3.10+, and Windows 10 or newer. -/// note | Note +Toga requires the use of either .NET Framework 4.x, or .NET Core 10. -Toga uses the [Python.NET](https://pythonnet.github.io) library to access the underlying Winforms GUI toolkit on Windows. Unfortunately, Python.NET doesn't always keep up with the release schedule of Python itself, and as a result, may not be compatible with recently-released versions of Python (i.e., a Python release with a version number of 3.X.0 or 3.X.1). If you experience problems installing Toga, and you're using a recently-released version of Python, try downgrading to the previous minor release (e.g. 3.13.9 instead of 3.14.0). +If you're on an x86-64 machine, .NET Framework 4.x is installed by default on Windows 10 and 11. Toga will use .NET Core 10 if it is installed. + +If you're using an ARM64 machine, and you're using a native ARM64 Python interpreter, you *must* use .NET Core 10. The [.NET Desktop Runtime can be downloaded from the .NET website](https://dotnet.microsoft.com/en-us/download/dotnet/10.0). If you're using an x86-64 interpreter on an ARM64 machine, Toga can use the .NET Framework install that is provided by default. -/// +Toga uses the [Python.NET](https://pythonnet.github.io) library to access the underlying Winforms GUI toolkit on Windows. Unfortunately, Python.NET doesn't always keep up with the release schedule of Python itself, and as a result, may not be compatible with recently-released versions of Python (i.e., a Python release with a version number of 3.X.0 or 3.X.1). If you experience problems installing Toga, and you're using a recently-released version of Python, try downgrading to the previous minor release (e.g. 3.13.9 instead of 3.14.0). If you are using Windows 10 and want to use a WebView to display web content, you will also need to install the [Edge WebView2 Evergreen Runtime.](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download) Windows 11 has this runtime installed by default. From 0876d60514ba570ed72e020b85582fb9e056a4c7 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 16 Apr 2026 11:45:34 +0800 Subject: [PATCH 4/4] Add changenote. --- changes/2782.feature.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changes/2782.feature.md diff --git a/changes/2782.feature.md b/changes/2782.feature.md new file mode 100644 index 0000000000..3079b2fff6 --- /dev/null +++ b/changes/2782.feature.md @@ -0,0 +1 @@ +Toga's WinForms backend can now be used on ARM64 machines with a native ARM64 Python interpreter.