Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Announcement: Proposed approach for windowing in Project Reunion #157

Closed
rkarman opened this issue Aug 27, 2020 · 69 comments
Closed

Announcement: Proposed approach for windowing in Project Reunion #157

rkarman opened this issue Aug 27, 2020 · 69 comments
Assignees

Comments

@rkarman
Copy link

rkarman commented Aug 27, 2020

Windowing in Reunion

We are excited to share some news with you today around the future of windowing for Windows developers. We have been listening to your feedback and concerns for this space over the years and we believe the approach we have chosen will address these in a positive way. This area has a lot of history (some of the features you use today, such as sizing and positioning windows, has been around since the first version of Win32) and a lot of investment in the developer community (your multi-windowed apps, your customized title bars, your customized dialogs and tool windows to create unique experiences, etc.) - we want to acknowledge and honor that as we go forward.

This post will outline our approach from a high-level perspective, our guiding principles, and our goals for the windowing space for Project Reunion. We are eager to get your feedback here, and we are open and ready to adjust our plans based on what you tell us. Nothing is set in stone - we are starting this journey here today, together with you.

A unified windowing space

In the past we have had two very different ways of "doing windowing" for Win32 and UWP - one very powerful but complex to work with even for basic windowing scenarios; one very limited in capabilities but easy to achieve the basics with.

For UWP we have been in a constant state of "catching up" on core functionality, and never being able to. While for Win32 we have been in a state of non-innovation, leaving developers behind because we have focused on bringing new features only to UWP where we can guarantee that guardrails are in place.

We heard you - this situation is not making anyone happy and moving between the two worlds is hard.

With Project Reunion we are taking a bold stance - we want all Windows developers to have the power of Win32 windowing at their disposal, but we also want to provide easy to adopt APIs that can provide consistent experiences across apps, as well as easy to use APIs that lower the bar of entry for new developers.

We also want the windowing model to be fundamentally the same, so that we create a familiar way of working for developers regardless if you chose UWP or Win32 as your application model.

Our approach in order to achieve this? A layered set of APIs.

Layers of APIs

We acknowledge that if you started with CreateWindowEx and used HWNDs for your app, you want to be able to continue to do so going forward. A re-write of your main window proc is just not going to be feasible. Therefore, we are bringing most of the windowing primitives from USER32 to Reunion. This gives you access to powerful APIs when you need them.

We also acknowledge that some things are really hard to do, or to get right for all situations, with the USER32 APIs, so we bring you AppWindow - a high-level windowing API surface that gives you access to a modern Windowing Model with an easier to use surface for areas where we have gotten a lot of feedback in the past, or where we want to help drive innovation, consistency in experience, or make it easier to adopt new features.

How is this different from the old Win32 vs UWP situation?

First, all these APIs are accessible to you regardless of process model - both UWP and Win32 have access to all the layers of the APIs. There might be some behavioral differences when calling the low-level APIs due to the security context of your app and whether it is running in a container or not. For example, the fact that we give you access to
lower level APIs from UWP does not mean we give you access to other processes or their windows, you’ll only be able to modify your own windows - the security context for UWP is not changed.

Secondly, we are giving you the ability to freely move from one layer to the other regardless of where you started from.

  • Started out by calling CreateWindowEx and got an HWND, but now you want to go into CompactOverlay? No problem, get an AppWindow object for your HWND and use the high-level scenario APIs!
  • Started out by creating an AppWindow, but now you want to tailor your experience beyond what the high-level API allows you to? No problem, get the HWND for your AppWindow and pass it to the lower-layer APIs.

Existing apps and their adoption to Reunion

For Win32 we touched on the approach already, by moving most of USER32 to Reunion we hope that you will have a straight-forward and easy path to adopt Reunion. Note that we are not saying that everything in USER32 will be available in Reunion and that there will be no work needed to move your Win32 app to Reunion - there will be parts of USER32 that will not being carried forward, but we will try to keep this to a minimum and limit the apps impacted.

For UWP the story is a little bit more nuanced. UWP have multiple windowing currencies, each with different limitations and life-time management. We are not going to preserve them all and move them to Reunion. As we mentioned earlier we are unifying the windowing model, this means changes to UWP that will require work. We are working through the details of the migration story for UWP depending on where you start from (CoreWindow, ApplicationView, AppWindow), and will start sharing that with you over the coming months. Our aim is to make it easy to migrate most UWP projects to Reunion for the windowing space, and we will do everything we can to help you come with us on the Project Reunion journey. If you have worked with AppWindow in UWP, you should be familiar with what we have in mind.

More details please!

We know that this post is light on technical details and completely lacks API shape information. This is intentional. We first wanted to share our approach for this space with you, to allow you to give feedback on this and influence it. As we align on the approach and start to move forward on the details, we want to design the APIs in the open together with you, not hand down a ready-made solution that we've designed in a vacuum. We hope you agree that this is the right approach, and we look forward to work out the details together with you for the initial release and for many years to come as Reunion grows.

Starting the journey together with you

Over the coming months, we will create functional and API specs here on GitHub and we are looking forward to a great partnership with the community. As a first step of this partnership we'd like to share our guiding principles and high-level goals for the windowing area as these will help inform everyone where we're coming from and what we're aiming for.

Guiding principles for Reunion windowing

We will support developers "where they are" – we will aim to support existing Win32 app developers with limited rewrite
of their existing code; we will aim to support existing UWP developers with an easy transition from AppWindow and
ApplicationView to Reunion windowing APIs.

We will design our new APIs with existing developers in mind, such that we do not leave existing Windows developers
behind or alienate them with "yet another solution"; for developers new to the Windows ecosystem we will strive to have
a low barrier of entry.

We will provide a full stack of APIs – powerful low-level primitives, targeted at expert developers that allow them to
innovate and create experiences beyond our own roadmap and imagination; high-level scenario APIs that allow for any
developer to light up our new features and take advantage of new form factors at a low cost.

Goals

  1. We will provide a global windowing currency across Win32 and UWP.
  2. Win32 apps shall be able to recompile to Reunion with only limited code changes for the windowing space.
  3. The windowing API for new projects, whether they be Win32 or UWP, will be a high-level, easy to use, API that follows
    modern development principles and patterns.
  4. We will provide a migration path from UWP AppWindow API onto the high-level Reunion Windowing APIs that is mostly automatable.
  5. Developers shall have access to the full spectrum of windowing APIs (both high- and low-level) with as few restrictions as possible. Ex. there may be a need to avoid certain window messages, events, or calling patterns when mixing between APIs of different "levels".

Non-Goals / Negative Goals

  • It is not our goal to bring the current versions of UWP AppWindow and ApplicationView APIs to down-level OS versions past where they were introduced.

Open Source

It is our goal to provide as much of the windowing stack for Project Reunion as Open Source as possible. We will listen to your feedback on what you need in this space and adapt as we move forward.

@MarkIngramUK
Copy link

Is there a plan for handling the pain (for Microsoft) of eternal backwards compatibility? As developers opt-in to Reunion it would be good to embrace the idea of deprecating functions in future versions, in order to provide the best APIs possible. Though I appreciate you probably don't want to think about past v1 release, I just wanted to point out how bonkers it is that Win32 still has support for 16-bit APIs (and even in UWP e.g. LocalAlloc and co).

@sylveon
Copy link

sylveon commented Aug 27, 2020

New APIs making use of LocalAlloc have been added as recently as Windows 8. LocalAlloc being present in UWP also hurts no one and makes porting old code easier, so it's a positive.

However I agree that we could drop some APIs like SetWindowLong (which is 1:1 replaced by SetWindowLongPtr)

@riverar
Copy link
Contributor

riverar commented Aug 27, 2020

Questions:

  • What is a "windowing currency"? (Please use plain English in all outward facing comms.)

  • What do you want from us? I presume this thread will just fill up with random complaints and feature requests. Is that what you want? Do you have any questions you need answers to?

@MarkIngramUK
Copy link

I'm just advocating for allowing old APIs to be removed, or updated, and for new APIs to be added. I guess if Reunion is shipped with the app, that would be reasonably trivial to achieve.

@smj389
Copy link

smj389 commented Aug 27, 2020

I'm just advocating for allowing old APIs to be removed, or updated, and for new APIs to be added. I guess if Reunion is shipped with the app, that would be reasonably trivial to achieve.

As Raymond Chen keeps reminding us, source compatibility is important to adoption. There is code out there that started with Win16 and is probably still with us today.

@dpaulino
Copy link

Win32 apps shall be able to recompile to Reunion with only limited code changes for the windowing space.

Regarding this goal, I noticed that Win32 was explicitly mentioned. For clarify, can someone confirm if UWP will also recompile to Reunion with limited code changes for the windows space? I apologize if the question doesn't makes sense, I'm still wrapping my head around Project Reunion

@smj389
Copy link

smj389 commented Aug 27, 2020

Win32 apps shall be able to recompile to Reunion with only limited code changes for the windowing space.

Regarding this goal, I noticed that Win32 was explicitly mentioned. For clarify, can someone confirm if UWP will also recompile to Reunion with limited code changes for the windows space? I apologize if the question doesn't makes sense, I'm still wrapping my head around Project Reunion

We will provide a migration path from UWP AppWindow API onto the high-level Reunion Windowing APIs that is mostly automatable.

@rkarman
Copy link
Author

rkarman commented Aug 27, 2020

Great questions Rafael! I'll try to address them as best I can.

  • What is a "windowing currency"? (Please use plain English in all outward facing comms.)

The object/construct you use to reference a window. In Win32 this is HWND, for UWP it is CoreWindow, ApplicationView and AppWindow depending on what APIs you are using. We want to make sure you can reference a window in the same way across the different app models, and also make sure that as a developer you don't have to think differently about a window based on what API created them.

  • What do you want from us? I presume this thread will just fill up with random complaints and feature requests. Is that what you want? Do you have any questions you need answers to?

I know that this announcement is light on technical details that may be needed in order for you to give deep and meaningful feedback on how this approach for windowing will work, benefit, or impact each of you and your specific app needs. But in general I want to bring windowing to top of mind of the community in order to set the stage for the specs that will start to show up for this space in the near future.

A couple of questions I want you to think about and try to answer as we continue the conversation (some of it on this post, some of it on new posts about specific features):

  • Do you think this we are taking the right approach for this space? If not - what are we missing?
  • Do you believe that a full layer of APIs is truly needed? (Or do you perhaps think one part or the other of the layers are not needed (I don't want to put words in anyone's mouths, so I'm being vague here)
  • Does bringing a lot of the user32 APIs to UWP mean that you are more likely to adopt UWP for future projects?
  • Does having access to a high-level windowing construct from the platform itself (AppWindow) add value to your existing Win32 app(s)? (this may be hard to answer until we share more of the feature details)

@rkarman
Copy link
Author

rkarman commented Aug 27, 2020

Is there a plan for handling the pain (for Microsoft) of eternal backwards compatibility? [...]

We are thinking hard about this one. As I wrote above we are targeting "most" of the windowing primitives, not all. This is intentional - we will weigh app compatibility and usage against "cleaner platform" and potential tradeoffs of not bringing an API forward. As part of the next steps we will be sharing what we believe are a good "first set" to bring forward and have a communication with you to align and adjust as needed.

@LanceMcCarthy
Copy link

From an appearance standpoint, my hope is that I can still use the best of what CoreWindow offers, but with the flexibility of some Win32 window features.

For example, the most asked for things for UWP CoreWindow has been things like custom window geometry and real transparency.

Easy Acrylic is still amazing so we don't want to lose that, so imagine being able to combine Acrylic with custom geometry without needing to write a custom graphics pipeline.

@mdtauk
Copy link

mdtauk commented Aug 28, 2020

Am I right in thinking that the initial version of this, when it is added to Reunion, will take us all back to the current windowing offered by Windows?

Are there plans and thoughts for adding new innovation to windows and windowing?

There was talk at Build 2018 I think, about actual new modern windowing concepts there were to come to UWP.
Will these come for all Reunion apps now?

And how far back will these innovations be supported, Windows 10 Threshold / Windows 8.1 / Windows 7?

image
image

@Felix-Dev
Copy link

Felix-Dev commented Aug 28, 2020

Does bringing a lot of the user32 APIs to UWP mean that you are more likely to adopt UWP for future projects?

@rkarman
When working on UWP apps specific pain points, compared to Win32 apps, for me have been so far:

  • The UWP app titlebar reserves some non-clickable space to the left of the min/max/close buttons. This makes it impossible to re-create custom Win32 titlebar experiences in UWP apps in certain cases. See issue Proposal: Titlebar Customization: Remove system reserved draggable region when providing an own draggable region microsoft-ui-xaml#1888 for more details.
  • When writing an app which will be run in the background most of the time, Win32 apps allow the running app's window(s) to be hidden from the taskbar. This is currently not possible for UWP apps. Some months ago, an API AppWindow.TryHide(Boolean shownInSwitchers) was spotted in an Insider SDK release which seems to be what I'm looking for here. Being shipped in an Insider SDK only for now though, the fate of this API is unknown to me (it might be shipped at some point, altered, or even removed - never to be released). Will this API be shipped and when?

@smj389
Copy link

smj389 commented Aug 28, 2020

Being able to handle more than one window from the same thread / message loop is key in Win32 and is really missing in UWP (unless I missed an API).

@mrlacey
Copy link

mrlacey commented Aug 28, 2020

one very limited in capabilities but easy to achieve the basics with

I always found the UWP windowing options to be more complicated than I would have liked. I would never have called them "easy". Making them ever "easier" in the future would be great.


The explanation of laying of APIs isn't clear. It sounds like all APIs will be available everywhere and does not explain how they will be layered.


How does microsoft/microsoft-ui-xaml-specs#71 relate to this?

@sylveon
Copy link

sylveon commented Aug 28, 2020

Being able to handle more than one window from the same thread / message loop is key in Win32 and is really missing in UWP (unless I missed an API).

AppWindow allows that, but ContentDialog can only be opened once per thread at a time. Which means if you use that you're forced to use threads anyways.

Worse even, XAML islands in a thread currently leaks if I just exit the thread after the window is closed, so I had to implement my own thread pool to keep the message loop running once the window is closed (because the Windows thread pool doesn't do that) to allow the cleanup to be performed correctly. Fun times.

@rkarman
Copy link
Author

rkarman commented Aug 28, 2020

Trying to reply to a couple of items in one go since this is not a threaded forum... I will also incorporate some of the feedback into the original issue so that new readers don't have to spelunk through the comments to get the some of the clarifications made here.

@LanceMcCarthy -

From an appearance standpoint, my hope is that I can still use the best of what CoreWindow offers,
but with the flexibility of some Win32 window features.

This is right at the core of what we are aiming for with this strategy.

Easy Acrylic is still amazing so we don't want to lose that, so imagine being able to combine Acrylic with custom geometry
without needing to write a custom graphics pipeline.

I can't yet detail the specific feature that can be mixed and matched between the layers here, but our goal is to limit the restrictions. So that, yes, if/when you are able to change the shape of your window with the lower level APIs you can do so even if you used a higher level API to say apply Acrylic.

@mdtauk -

Am I right in thinking that the initial version of this, when it is added to Reunion, will take us all back to the current
windowing offered by Windows?

Not sure I parse this the right way, so please be patient with me as I try to answer it.
Will you be able to do a lot more with windowing from UWP? Yes. With the initial version you will be able to do a lot of what Win32 apps can do today in terms of window customization and manipulation. But not to windows outside of your own process.

Will the high-level Reunion AppWindow object be more powerful than what is available in UWP today through CoreWindow/ApplicationView, and UWP AppWindow? Depends. We are working on the roadmap and engineering plan, but our intent is to make it available as early as possible and that might limit the amount of features we include in the first release. But we do have ideas and plans for more, which leads me into the next part:

Are there plans and thoughts for adding new innovation to windows and windowing?

Yes, there are. 😀 We have some interesting features that we want to bring to the world, but we are not yet ready to talk about some of them. As for the 2018 //build/ talk - yes, that was me doing that talk and that was the plan we had at that time. The high-level goals are still there in that we keep seeing innovation in user interaction and device types, and we want to make sure that our windowing model is capable of handling this.

But will all the features we talked about back then come to Reunion? Yes and no. Some feature are no longer relevant, some are being satisfied by access to the lower-level APIs, some are still on the roadmap though and when we are ready to we will bring them to Reunion. More details on the specifics as we start to publish specs and along with them a roadmap - which we will adjust based on feedback and needs of the community.

And how far back will these innovations be supported, Windows 10 Threshold / Windows 8.1 / Windows 7?

I am truly sorry to not be able to talk to this part in details just yet, but this is something that is being worked on across the Project Reunion as a whole. What I can say is that we will do our best to align with the larger project's goals to the extent that it is technically feasible. I hope to have more details to share during fall.

@Felix-Dev -
Regarding the Title Bar customization - this is great feedback and something we will make sure is covered in the specs for that feature area.

When writing an app which will be run in the background most of the time, Win32 apps allow the running app's window(s) to
be hidden from the taskbar. [...] Will this API be shipped and when?

This API will be part of Reunion. Not necessarily with that specific shape, but it is part of the requirements I have for the Reunion AppWindow, yes. There should be more info coming with that feature spec.

@mrlacey -

The explanation of laying of APIs isn't clear. It sounds like all APIs will be available everywhere and does not explain how they
will be layered.

The higher-level APIs will all be built using the lower-level primitives. There will be no "black box" and completely different stack powering the higher-level APIs like today with the difference between CoreWindow and HWND.

How does microsoft/microsoft-ui-xaml-specs#71 relate to this?

XAML is a framework that builds on, and sometimes abstracts, platform constructs. As such it will in some cases provide it's own version of similar objects in order to provide developers with a familiar programming/object model. XAML is building on top of what we provide at the platform layer, and we are working across the teams to align between the different layers and make sure we can support each other's roadmaps and visions.

some general closing comments for this reply

For everyone on this thread - thank you for your comments and feedback so far, I really appreciate this.

If I've missed answering a question it is not on purpose, so please forgive me and let me know so that I can try to answer that too.

If there is something that is still unclear, please do not hesitate to tell me and I will do what I can to bring clarity (and again, I will update the original issue with some of the details from the comments here).

@pjmlp
Copy link

pjmlp commented Aug 31, 2020

Sorry to say, but I got even more confused how things will shape up with Reunion.

Before Reunion's announcement it seemed that UWP adoption was in a slow and steady rate, but now with Reunion, replacement of C++/CX with C++/WinRT (with related productivity drop), uncertain future for .NET AOT with WinUI, alongside other attempts to drive UWP adoption, it seems to me that most of us are better off with outdated Win32, Forms and WPF until everyone at Microsoft can finally make their mind what Windows development should be like.

As for the proposal, it looks good, assuming it gets delivered and doesn't get dropped like many other Windows 8 - 10 related stuff.

@MarkIngramUK
Copy link

@rkarman will any new API additions be added to the OS as well as Project Reunion, for those of us that don't need to consider backwards compatibility?
An area that I would love to see made simpler in Win32 would be custom title bars. In our apps we render 100% of the UI including the title bar and whilst we've already done it, it just seems like a hack (we have to process all mouse input by returning HTCLIENT because Windows prevents WM_LBUTTONUP for anything which isn't the Close button).

@shaggygi
Copy link

shaggygi commented Sep 1, 2020

Is this part of the effort @marb2000 was doing for windowing with WinUI? For example, I recall there being some sort of proposal over on https://github.com/microsoft/microsoft-ui-xaml-specs.

UPDATED: Oops. Just noticed this was already mentioned.

@ianhan
Copy link

ianhan commented Sep 1, 2020

This document has hard line breaks at the end of each line which makes it hard to read when it wraps at larger font sizes. IMO this is always the way we should have done it - providing a glide path from Win32 so folks can make incremental progress on their giant Win32 apps. Big thumbs up.

@wjk
Copy link

wjk commented Sep 1, 2020

I have some questions on the scope of this plan (which, by the way, I applaud). Will this mean that I can place arbitrary HWNDs in my AppContainer window, or arbitrary WinUI controls into my HWND? Will this mean I will be able to take an HDC from GDI+ and use APIs like those in Windows.UI.Composition on it?

Most importantly: Will there be a way to write drawing code under the assumption of 100% DPI, and have it automatically scaled up (locations, thicknesses, corner radii, everything) to look exactly the same at higher DPI settings without my having to do math with my locations/thicknesses/etc? WPF does this for me, but that technology has stagnated. While Windows Forms is much more active and lightweight, which is why I prefer it, high-DPI drawing in GDI+ is squarely the responsibility of the developer, and it’s hard.

Finally: You mention lifting some of the APIs in user32.dll into Reunion. Does this actually mean we will be (hopefully) seeing code in this repo that was once in user32.dll, gdi32.dll, or other files? If so, I can’t wait for the day when that code arrives. Thanks so much!

@jtorjo
Copy link

jtorjo commented Sep 1, 2020

Does this mean we'll finally have the ability to place a window where we want on the screen in UWP? And set its state (minimize, restore, maximize)? That would be insanely awesome!

@huoyaoyuan
Copy link

As you are evoluting the whole UI layer, I really want you to rewrite Visual Studio with it, to prove its functionality, and improve Visual Studio's performance.
UWP was bound to a security model that's unsuitable for VS. But since you are going to decouple them, I want VS to be a real-world sample of best practices.

@kmgallahan
Copy link

I presume this thread will just fill up with random complaints and feature requests. Is that what you want?

I really want you to rewrite Visual Studio

@riverar 😂

Feel free to add my comment to the list of those that are off-topic and deletion worthy.

@nCastle1
Copy link

nCastle1 commented Sep 8, 2020

I know this is about the API, but I'm wondering to what degree the API changes will involve implementation changes for UWP.

There is still a lot of jank with the UWP windows that causes problems that Win32/WPF/etc. apps don't have:

  1. Apps don't always respond to Window size changes; unique to UWP and affects even built-in apps like Bing Maps.
  2. UWP apps depend on explorer.exe running in order to function properly (e.g. respond to Window size changes). This is a bizarre dependency for modern apps
  3. Built-in window components (e.g. dialogs) don't handle mixed-DPI well; I'm not sure if that's due to the component implementation or the windowing system, but I haven't seen anything like it in Win32 apps.
1 2 3
n7JDOD3T6j dmbWyeqBtv PickerHost_dfPJadTrCy

Will UWP/WinUI windows under project reunion be built on the same foundations as the more reliable Win32 APIs?

@riverar
Copy link
Contributor

riverar commented Sep 8, 2020

@nCastle1 Regarding item 1: That's a long standing bug. Microsoft is very aware of it, and I always remind them of it.

@Poopooracoocoo
Copy link

have they also seen the issue of File-New-Project/EarTrumpet#349 and sourcechord/FluentWPF#42 (among many others) or the 1903 snap bug?

@sylveon
Copy link

sylveon commented Sep 10, 2020

See this comment: File-New-Project/EarTrumpet#349 (comment)

@rkarman
Copy link
Author

rkarman commented Sep 24, 2020

Adding #203 to this thread. We will incorporate this into the requirements for window positioning and behavior for FullScreen for Reunion windowing.

Also an update on this thread in general:
Thank you all for the valuable input and feedback on this topic. We are now working on incorporating this and writing up the initial API proposal for this area.

Next step will be to get the feature specs in order and post them here in GitHub (they may end up coming from other PMs than me, so I'll make sure to update this post with links to PRs). As part of getting the specs in place we will continue to monitor this thread, but once the PRs are out we hope that you will engage there on the particular feature areas as well.

@mdtauk
Copy link

mdtauk commented Sep 28, 2020

Is there a compiled list of windowing problems from Win32 to WPF and UWP?

Can Reunion offer fixes to long standing windowing and window painting problems?

Reunion is essentially opt in, so if some of these fixes require code alterations - that is a sensible time to introduce it.

Rather than just using Win32 as a baseline, and not trying to build on what is already there.

@AzAgarampur
Copy link

@mdtauk We should make one. We can start with things like WPF's & UWP's incorrect handling & drawing of the nonclient-area, WPF per-monitor v2 dpi, WPF's incorrect WindowChrome default values, UWP's missing window borders, Win32's very inconsistent window border(s) (for some strange reason this doesn't happen in dark mode), and add to the list.

@Poopooracoocoo
Copy link

but will microsoft actually do anything about those issues?

@pjmlp
Copy link

pjmlp commented Sep 30, 2020

After all the code rewrites we went through since Windows 8, and .NET Core introduction, I am very much opposed to anything that Microsoft ask us to rewrite, unless it is for a 100% from scratch application.

So however these bugs get fixed, hopefully it isn't by asking us to do yet another rewrite.

@benstevens48
Copy link

I'd like to draw attention to a flaw in the implementation of some of the existing ApplicationView APIs. I don't entirely understand the reasons why, but apparently some of the APIs can cause a nested message pump, which has the potential to cause all sorts of problems - see this comment for details microsoft/microsoft-ui-xaml#3297 (comment). It would be good if the new implementation avoided this if possible, or if not possible perhaps it could provide both sync and async alternatives for such APIs (where the async version would not have this problem).

@sylveon
Copy link

sylveon commented Oct 7, 2020

Reentrancy is normal and expected in Win32

@weltkante
Copy link

weltkante commented Oct 7, 2020

Reentrancy is normal and expected in Win32

Reentrancy is something way different from a nested message pump, reentrancy can happen for something as simple as an event or callback. Nested message pumps in general are evil because they can silently drop messages. Also, the huge majority of the win32 API will just do some computation and return a result, not call back into user code, and certainly not run a message pump. You probably had some specific scenario in mind, but as a statement about "the win32 API" this is simply wrong.

As far as the topic of nested message pumps is concerned, some applications have the requirement that the message pump be consistently provided by the hosting application, for example because it uses WM_APP style messages (sent to the application message loop instead of targeting a HWND) or does other processing before blocking for the next message. For example WPF interop also requires cooperation from the message loop, as do many low level frameworks, requiring a way to peek at messages - local message pumps usually don't provide that and cause lot of annoyance in interop scenarios.

Async APIs are the proper way to implement this because they allow the caller to decide whether he needs a message pump, and if so, how to implement it. Feel free to provide a helper method implementing a "DoEvents until the IAsyncAction completes" style message loop for convenience for people who do not care, but if Project Reunion is serious about bridging different frameworks it should avoid implicit nested message loops wherever it can, they only cause problems.

@rickbrew
Copy link

rickbrew commented Oct 7, 2020

I've seen re-entrancy in desktop apps, but it was because .NET synchronization primitives (e.g. Monitor / lock) will start pumping the message queue so that inter-thread COM marshaling doesn't get starved (which can result in deadlocks). This can be solved with a custom SynchronizationContext that can be told to disabled pumping for certain regions of code. I was getting reentrant WM_PAINT messages which was not working out well, especially when mixed with stateful Direct2D render targets (you can't nest BeginDraw).

@sylveon
Copy link

sylveon commented Oct 7, 2020

COM is full of inner message loops and it has caused me a lot of trouble in development. Never had dropped messages but it caused me unexpected reentrancy (which lead to use-after-free in some scenarios) I had to guard against.

SetLayeredWindowAttributes has also triggered an inner message loop.

@sylveon
Copy link

sylveon commented Oct 7, 2020

Not to mention that dialog boxes, file browsing dialogs, OLE functions, etc. also all have an inner message loop

@weltkante
Copy link

weltkante commented Oct 7, 2020

COM is not the win32 API, it is beyond that, and yes, often reentrant. However it also has API to cooperate with the hosting application, should it need to. Just like rickbrew above mentioned that .NET has SynchronizationContext to opt out of nested message loops. Naive nested message loops often do not provide something to work around the shortcomings of nested message loops.

Some win32 APIs around modal dialogs may have message loops, but they are either isolated (you need to intentionally call something which implies showing a modal dialog) or provide ways to work around them.

SetLayeredWindowAttributes has also triggered an inner message loop.

Thats the first I hear of that, maybe you just mean reentrancy (it may very well send window messages, which does not require a message loop, these are entirely different things! message loops are bad, sending window messages is normal callback behavior, which can cause reentrancy but doesn't cause all the bad stuff nested message loops do)

From your response I see you are mixing up a few things, which are conceptually clearly separated in the implementation of Windows. Sending window message doesn't require a message loop, it is equivalent to what modern languages use events or callbacks for. This can cause reentrancy but is not equivalent to a message loop. Message loops wait for something and are used for modal behavior (like a message box, task dialog or resizing behavior - which are all very isolated scenarios and not arbitrary win32 APIs, often with dedicated ways to work around them - for example you explicitely call the message box or task dialog yourself and could use your own implementation if you chose to; for resizing there are dedicated messages to warn you about it; COM has a dedicated API, etc.)

What I'm saying is that future design should not just stick a nested message loop somewhere waiting for some condition and assume its fine because everyone else is doing it - because everyone else is not doing it - its very specialized behavior, which needs dedicated API to work around its shortcomings (like COM provides with IMessageFilter or .NET provides with SynchronizationContext). For new APIs the simplest and best solution is just not doing it, returning an IAsyncAction or something semantically equivalent, leaving full control at the application to provide the message loop.

@sylveon
Copy link

sylveon commented Oct 7, 2020

My bad, it was SetWindowLong, and not actually an inner loop, but that was still very much unexpected since the message I was receiving from that is entirely unrelated to the operation I was doing (it triggered a map clear, but the caller had an iterator to the map still, leading to use after free):
image

I am not a .NET programmer, so can't "just use" a SynchronizationContext. Async APIs are a pain in C++ (ignoring lack of IDE support), because you can't inspect local variables with the debugger (neither VS nor WinDBG), and stack traces with them are essentially useless. At least inner message loop stack traces make sense, and you can use regular debugging features.

image

@weltkante
Copy link

weltkante commented Oct 7, 2020

Thats actually not a "message loop" - there is no waiting and pumping messages until an exit condition is met. It is just sending a window message, aka callback or event. Yes this is reentrancy, but this is not a message loop or message pump. No other messages will be delivered besides the ones being part of the implementation of SetWindowLong.

I am not a .NET programmer, so can't "just use" a SynchronizationContext.

Then it wouldn't help you anyways, it only suppresses the message pump in the .NET framework, nothing in the win32 API. And it wouldn't save you from reentrancy present in the win32 API.

I'm standing by my point, implicit message pumps which deliver arbitrary queued messages (and drop/delay some others) while waiting for an exit condition to become true are a bad thing and should be avoided in any framework wherever possible, to save people having to work around them when they have their own top level message loop in their application.

@ClosetBugSlayer
Copy link

This whole battle comes down to: will each framework's controls respect each others' airspace?

@ChrisGuzak
Copy link
Member

ChrisGuzak commented Nov 24, 2020

The earlier disucssion of unexpected reentrancy between @sylveon and @weltkante raises a good topic, what threading model should the reunion windowing design support? ASTA, STA, BSTA, all 3?

@MikeHillberg what will WinUI 3 support?

@mevey mevey unpinned this issue Dec 11, 2020
@JaiganeshKumaran
Copy link
Contributor

The current Sticky Notes app is pure UWP with no full-trust but still can draw custom title bar without system icons and can also disable the system title bar context menu yet still works on 10x and non-Desktop platforms. Microsoft should open up this functionality to other developers.

@microsoft microsoft locked and limited conversation to collaborators Jan 13, 2021
@microsoft microsoft unlocked this conversation Jan 13, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Projects
None yet
Development

No branches or pull requests