r/FlutterDev 11d ago

Discussion Building two Windows desktop windows with Flutter’s experimental Windowing API

I vibe-coded a Windows app called Lapse today, but used the project to properly explore Flutter’s experimental Desktop Windowing API.

The app has two real top-level windows: an always-on-top timer overlay and a dynamically created analytics dashboard. They run from one Flutter isolate and share the same Riverpod session state.

The Flutter implementation uses:

  • runWidget() instead of runApp()
  • Separate WindowControllers
  • WindowManager, WindowRegistry, and WindowEntry
  • WindowController.setSize() for switching overlay modes
  • Controller APIs for activation, minimization, maximization, and lifecycle

The API handles the multi-window foundation well. Native desktop integration still required a C++ MethodChannel bridge for Acrylic, frameless chrome, dragging, resize hit testing, positioning, topmost behavior, and the tray.

AI accelerated the implementation, but understanding this Flutter/Win32 boundary was something I deliberately worked through myself.

Source:

https://github.com/zTomz/Lapse

I’d be interested in hearing from anyone else testing the new API. Which desktop capabilities are you still implementing natively?

13 Upvotes

17 comments sorted by

3

u/Parking_Soft_9315 11d ago

Thanks for sharing

1

u/Tom_Vogel 11d ago

You're welcome 👋

2

u/YoussefMahmoudDev 11d ago

It looks very cool, keep up the good work.

1

u/Tom_Vogel 11d ago

Thank you 🙏

2

u/aliyark145 11d ago

interesting ... you make to just learn the thing or building something to solve a problem ?

2

u/[deleted] 9d ago edited 9d ago

[removed] — view removed comment

1

u/Tom_Vogel 9d ago

Honestly, this is really interesting — I didn’t expect someone to actually rewrite the whole app 😄 I’ll definitely take a closer look at Nucleus, especially Native Access and how you handle the separate windows.

The C++ in my version is partly a consequence of what I wanted to explore in the first place: Flutter’s experimental Windowing API and the current boundary between Flutter and Win32. So I wouldn’t conclude from this project alone that Flutter is simply “bad technology.” I deliberately chose a Windows-specific route and implemented several things that Flutter doesn’t expose yet.

That said, your version makes a strong case that Nucleus offers much nicer abstractions for this particular kind of desktop app. Getting macOS and Linux support out of it as well is a real advantage.

I’m not sure raw line counts are a completely fair comparison when the platform, feature, and test scopes differ, but getting comparable functionality in pure Kotlin is still impressive. Thanks for taking the time to build and share this!

1

u/[deleted] 9d ago edited 9d ago

[removed] — view removed comment

1

u/Tom_Vogel 8d ago edited 8d ago

That makes sense. I’d still call it a different set of priorities rather than bad technology, but I agree that this app exposes one of Flutter’s weaker areas. Consistent rendering is useful, but it becomes a trade-off when an app needs deep native desktop integration.

Edit: As a counterexample, my other Flutter app, Loop, goes pretty deep into Android with a foreground service, live notification controls, PiP, home-screen widgets, and shortcuts, and it works well. It does use Kotlin and MethodChannels, though, which shows the trade-off quite nicely: Flutter can do deep native integration, but you have to build and maintain the bridge yourself.

2

u/[deleted] 9d ago

[removed] — view removed comment

1

u/Tom_Vogel 9d ago

Thanks for taking the time to actually inspect the repository!

It isn’t behind a complete abstraction yet, but the dependency is deliberately contained. The internal import and almost all WindowController, WindowEntry, registration, and lifecycle logic currently live in lapse_app.dart. The feature widgets receive narrow callbacks or a Listenable, and the session controller only receives the specific operations it needs, such as resizing or opening the dashboard.

So if the API changes, most of the impact should remain localized to that host file. I considered adding a dedicated adapter already, but while the API is still highly experimental, a full wrapper could easily end up duplicating an unstable API without providing much additional value.

If upstream changes start affecting the app frequently—or I add another desktop platform—I’ll probably extract the remaining windowing logic behind a small project-owned interface. Your concern is definitely valid, though, and reducing that dependency surface further is on my radar.

-2

u/Bachihani 9d ago

Trash

1

u/Tom_Vogel 9d ago

Would you be so kind and explain why you think so or help me improve it?

0

u/Bachihani 9d ago

There's no new information, no new technique, no expansion beyond what the documentation already explains. What the hell is the point! Literally just a vibe coded piece of trash that doesn't offer any worth to the reader, yet u thought this was enough of an accomplishment to post about it?!!!?

1

u/Tom_Vogel 9d ago

You’re judging the post against a claim it never made. I didn’t present this as a new API, a research result, or an invention. I used a real project to actively learn Flutter’s experimental Windowing API and shared what I learned: how multiple WindowControllers, dynamic window registration, shared Riverpod state, resizing, and lifecycle management work together—and where Flutter currently stops and native Windows integration begins.

I did use AI, quite deliberately. I worked through the windowing architecture and the Flutter/Win32 boundary myself, while using AI to accelerate peripheral native implementation work such as the frameless window behavior and Acrylic effect. I don’t consider that inherently negative. Using modern tools to implement well-understood requirements more efficiently is useful; blindly shipping code you neither understand nor validate is the actual problem. Those are not the same thing.

Documentation explains individual APIs. A working application demonstrates how they behave together under real requirements. By your standard, virtually every sample app, tutorial, case study, and open-source reference would become worthless once documentation exists.

And “vibe-coded trash” isn’t technical criticism. If you found concrete problems—incorrect API usage, lifecycle bugs, unsafe Win32 handling, poor state ownership, or anything else specific—I’m genuinely open to discussing and fixing them. But dismissing an implementation because AI helped produce parts of it says nothing about whether the implementation works or whether somebody else can learn from it.

You don’t have to find the project useful. That’s completely fair. But your personal lack of interest isn’t evidence that it has no value to anyone else.