beeware / toga

A Python native, OS native GUI toolkit.
https://toga.readthedocs.io/en/latest/
BSD 3-Clause "New" or "Revised" License
4.39k stars 684 forks source link

Add a WinUI3 backend #2574

Open jhi2 opened 6 months ago

jhi2 commented 6 months ago

(Ticket content has been edited significantly from the original to provide better guidance on the feature request)

What is the problem or limitation you are having?

Toga's look and feel on Windows currently uses Winforms, which doesn't reflect the current look and feel of Windows apps.

Describe the solution you'd like

We should add a WinUI3 backend.

Describe alternatives you've considered

Continue to use Winforms.

Additional context

The prerequisite for this backend is the development of Python bindings for WinUI3.

KubaO commented 2 months ago

But having now implemented 4 different approaches of accessing it from Python, the one I think is best is to just generate C++ code to do all the GUI side and have it call back into Python.

WinUI and WinRT have C++ projections, they are not C++-native. The C++ code drops down to good old COM, so there's little benefit to the C++ shim if we want to use it from Python. C# does the same. We might as well use the same COM interfaces that the C++ projection uses, but expose them Pythonically as Python classes etc.

And that's what pywin32more does - it uses low-level COM directly, via ctypes. And it exposes the non-COM Win32Api as well. Since it's machine-generated, it provides all the constants, structures and functions that the C Win32 headers provide. Using it feels fairly natural to me.

At the moment, there is no other Python projection of Windows APIs that is competitive IMHO.

freakboy3742 commented 2 months ago

Tagging @th3w1zard1 on this; it looks like pywin32more might implement the sort of reflective binding that we've been discussing in the context of #2786. That might make it a better match than comtypes for that work, while also leaving the door open for a full WinUI3 backend.

th3w1zard1 commented 2 months ago

From what I've researched, yes pywin32 is a solution and can directly replace comtypes.

I've spent several weeks on the ifileopendialog/ifilesavedialog, learning com programming and trying to figure out how the heck it would work through Python. One of the first things I've tried was looking into pywin32, as many stackoverflow posts I came across were using it. I came across several problems:

There were a few benefits such as:

Looking through their codebase, I seriously could not figure out how to wrap the com interface. I experimented around with interop from comtypes <--> pywin32. and anytime I would come across such a stackoverflow post it would either never integrate or the code just wouldn't make sense. Naturally the next thing I tried was to see if my code would run in C++. Sure did. So the issue straight up seemed to be pywin32 or how I was invoking it.

and finally that is when I considered comtypes It took a few hours to define the interfaces I wanted (pinvoke.net is a great resource), I'm pretty sure it worked the first time.

tldr if there are users highly familiar with pywin32 and can properly document toga's interaction with it, and provide a plan forward, I think it's a far better solution than comtypes.

edit: the early versions of my code still linger at the back of my mind as I keep thinking 'there's literally zero reason this is not working right now comparing to the C/C++'. It's exciting I might be getting an answer and the understanding of why I couldn't get my code working :)

freakboy3742 commented 2 months ago

From what I've researched, yes pywin32 is a solution and can directly replace comtypes.

To clarify - pywin32 and py-win32more/win32more are two different projects. The discussions on this ticket have been about the latter.

jhi2 commented 2 months ago

From what I've researched, yes pywin32 is a solution and can directly replace comtypes.

To clarify - pywin32 and py-win32more/win32more are two different projects. The discussions on this ticket have been about the latter.

My COM post was about the former.

th3w1zard1 commented 3 weeks ago

From what I've researched, yes pywin32 is a solution and can directly replace comtypes.

To clarify - pywin32 and py-win32more/win32more are two different projects. The discussions on this ticket have been about the latter.

My COM post was about the former.

Yeah exactly... so what am I missing here?

Could we talk about what is happening to this and #2786 ...? I'd like to know if it'd be worthwhile to continue holding off with comtypes if we believe something better could be implemented here?

KubaO commented 3 weeks ago

py-win32more is a projection of the full Windows API. It includes pretty much everything documented by MS. It’s not just a way to consume winrt api. It is a Python way of using Windows. I am using it professionally. It covers everything that comes in Windows SDK headers. It also has runtime type checking that helps avoid crashes that the dynamicism of Python would otherwise make easy to run into.pywin32 is a small projection of WinAPI - it covers a small part of it, maybe 20%? comtypes is just a framework one could use to consume winrt (with some pain). You’d still be typing in the signatures of stuff.As far as I am concerned, win32more is THE way to use Windows APIs in Python. There’s another professional projection of WinAPI that includes winrt stuff - Microsoft’s own winrt package on pip. Caveat emptor as MS had a tendency of dropping OSS projects randomly.If win32more’s strength is the simplicity of implementation, complete coverage of the APIs, and ease of vendoring if ever needed, winrt’s strength is the example code - there is a lot of it, and it’s pretty good. In most cases, „translating” it to win32more is trivial and takes changing the imports. Other minor adjustments may be needed too.I have more trust in win32more’s longevity than winrt’s. Should the worst happen, I am familiar enough with it to continue maintaining it. I have a fairly large internal project that uses it.I’ve looked at how much work it would be to get a proof of concept WinUI 3 backend for toga that can get at least a few of the more complex examples working. I’ll now shut up and work on that instead. Expect a PR for the PoC so that we can at least have something concrete to talk about :)2. nov. 2024 kl. 5:22 am skrev Benjamin Auquite @.***>:

From what I've researched, yes pywin32 is a solution and can directly replace comtypes.

To clarify - pywin32 and py-win32more/win32more are two different projects. The discussions on this ticket have been about the latter.

My COM post was about the former.

Yeah exactly... so what am I missing here? Could we talk about what is happening to this and #2786 ...? I'd like to know if it'd be worthwhile to continue holding off with comtypes if we believe something better could be implemented here?

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>

freakboy3742 commented 3 weeks ago

From what I've researched, yes pywin32 is a solution and can directly replace comtypes.

To clarify - pywin32 and py-win32more/win32more are two different projects. The discussions on this ticket have been about the latter.

My COM post was about the former.

Yeah exactly... so what am I missing here?

I'm not sure who this question is directed at - but personally, I have no idea why pywin32 is being mentioned at all.

Could we talk about what is happening to this and #2786 ...? I'd like to know if it'd be worthwhile to continue holding off with comtypes if we believe something better could be implemented here?

From my personal perspective - nothing is happening here. This ticket exists to flag the fact that yes, we'd like a WinUI3 backend. It's not on my own roadmap, nor is it likely to be in the near future. However, if someone were to contribute a WinUI3 backend, I'd look at it.

To that end, the fundamental issue that needs to be resolved at this point is the interface that will be used to implement the Python-WinUI3 bridge. The Winforms backend uses python.net. That provides a way to invoke Winforms APIs from Python in a format where it's obvious how to read official Winforms documentation and turn that into Python code. I don't use Windows on a daily basis, and I'm not deeply familiar with Windows GUI programming, but I can use Python.net to read Winforms documentation and implement Toga's APIs. What is the equivalent for WinUI3? Based on what has been said in this thread, win32more sounds (to me) like the most viable option - but I'm saying that on the basis of no practical experience, and a single example app presented above. I haven't explored what (if any) limits the win32more approach has when it comes to more complicated widgets, the stability/maintainablity of the win32more project, or whether it addresses any of the issues that currently face the winforms backend (e.g., support for ARM architectures, support for widgets like DetailedList or Tree, or modern dialog support).

As for #2786 specifically - nothing has changed since my last comment. The most pressing issue is that the testbed tests are currently failing. That needs to be resolved. I've already provided some pointers; if you need something more specific to get unstuck then you'll need to indicate where you need help.