Matthew Kosarek 97c11cf89a
Implement Regular Windows for the win32 framework + add an example application for regular windows (#173715)
## What's new?
- Implement and test `_window_win32.dart`, the Win32 implementation of
`_window.dart` 🎉
- Wrote a bunch of tests in `window_win32_test.dart` which uses a mock
API barrier to mock the native Win32 layer
- Update `BaseWindowController` to extend `ChangeNotifier` and use it to
inform the `WindowScope` of when things change
- Made `RegularWindowController.empty()` a non-internal constructor, as
it is needed by implementations
- Added a _large_ example application for windowing where users can test
out different windowing concepts and see how they work!

To test, simply run the tests or try out the example app!

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
2025-09-26 13:37:02 +00:00

103 lines
3.0 KiB
Dart

// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// ignore_for_file: invalid_use_of_internal_member
// ignore_for_file: implementation_imports
import 'dart:io';
import 'package:flutter/material.dart';
import 'app/models.dart';
import 'app/window_content.dart';
import 'app/main_window.dart';
import 'package:flutter/src/widgets/_window.dart';
class MainControllerWindowDelegate with RegularWindowControllerDelegate {
@override
void onWindowDestroyed() {
super.onWindowDestroyed();
exit(0);
}
}
void main() {
WidgetsFlutterBinding.ensureInitialized();
runWidget(MultiWindowApp());
}
class MultiWindowApp extends StatefulWidget {
const MultiWindowApp({super.key});
@override
State<MultiWindowApp> createState() => _MultiWindowAppState();
}
class _MultiWindowAppState extends State<MultiWindowApp> {
final RegularWindowController controller = RegularWindowController(
preferredSize: const Size(800, 600),
title: 'Multi-Window Reference Application',
delegate: MainControllerWindowDelegate(),
);
final WindowSettings settings = WindowSettings();
late final WindowManager windowManager;
@override
void initState() {
super.initState();
windowManager = WindowManager(
initialWindows: <KeyedWindow>[
KeyedWindow(
isMainWindow: true,
key: UniqueKey(),
controller: controller,
),
],
);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final Widget mainWindowWidget = RegularWindow(
controller: controller,
child: MaterialApp(home: MainWindow()),
);
return WindowManagerAccessor(
windowManager: windowManager,
child: WindowSettingsAccessor(
windowSettings: settings,
child: ListenableBuilder(
listenable: windowManager,
builder: (BuildContext context, Widget? child) {
final List<Widget> childViews = <Widget>[mainWindowWidget];
for (final KeyedWindow window in windowManager.windows) {
// This check renders windows that are not nested below another window as
// a child window (e.g. a popup as a child of another window) in addition
// to the main window, which is special as it is the one that is currently
// being rendered.
if (window.parent == null && !window.isMainWindow) {
childViews.add(
WindowContent(
controller: window.controller,
windowKey: window.key,
onDestroyed: () => windowManager.remove(window.key),
onError: () => windowManager.remove(window.key),
),
);
}
}
return ViewCollection(views: childViews);
},
),
),
);
}
}