A Flutter plugin to create and manage multiple windows on desktop platforms.
| Windows | ✅ |
| Linux | ✅ |
| macOS | ✅ |
Add desktop_multi_window to your pubspec.yaml:
dependencies:
desktop_multi_window: ^latest_versionIn your main() function, initialize multi-window support before running your app:
import 'package:desktop_multi_window/desktop_multi_window.dart';
Future<void> main(List<String> args) async {
WidgetsFlutterBinding.ensureInitialized();
// Get the current window controller
final windowController = await WindowController.fromCurrentEngine();
// Parse window arguments to determine which window to show
final arguments = parseArguments(windowController.arguments);
// Run different apps based on the window type
switch (arguments.type) {
case YourArgumentDefinitions.main:
runApp(const MainWindow());
case YourArgumentDefinitions.sample:
runApp(const SampleWindow());
// Add more window types as needed
}
}Use WindowController.create() to create and manage new windows:
// Create a new window
final controller = await WindowController.create(
WindowConfiguration(
hiddenAtLaunch: true,
arguments: 'YOUR_WINDOW_ARGUMENTS_HERE',
),
);
// Show the window (if hidden at launch)
await controller.show();Get all window controllers and manage them:
// Get all windows
final controllers = await WindowController.getAll();
// Find a specific window by business ID
for (var controller in controllers) {
final args = parseArguments(controller.arguments);
// Check window type
if (args.type == YourArgumentDefinitions.sample) {
await controller.center();
await controller.show();
return;
}
}
// Listen to window changes
onWindowsChanged.listen((_) {
// Handle window changes
});Use WindowMethodChannel for bidirectional communication between windows:
// In the target window, set up a method call handler
const channel = WindowMethodChannel('my_channel');
channel.setMethodCallHandler((call) async {
switch (call.method) {
case 'play':
// Handle the method call
return 'success';
default:
throw MissingPluginException('Not implemented: ${call.method}');
}
});
// From another window, invoke methods
const channel = WindowMethodChannel('my_channel');
final result = await channel.invokeMethod('play');Create an extension to add custom functionality:
import 'package:desktop_multi_window/desktop_multi_window.dart';
import 'package:window_manager/window_manager.dart';
extension WindowControllerExtension on WindowController {
Future<void> doCustomInitialize() async {
return await setWindowMethodHandler((call) async {
switch (call.method) {
case 'window_center':
return await windowManager.center();
case 'window_close':
return await windowManager.close();
default:
throw MissingPluginException('Not implemented: ${call.method}');
}
});
}
Future<void> center() {
return invokeMethod('window_center');
}
Future<void> close() {
return invokeMethod('window_close');
}
}And now, you can center or close the window in the other window:
final controller = await WindowController.fromWindowId(other_window_id);
// Center the window
await controller.center();
// Close the window
await controller.close();Each window created by this plugin has its own dedicated Flutter engine. Method channels cannot be shared between engines, so plugins must be manually registered for each new window.
Edit windows/runner/flutter_window.cpp:
- Add the include at the top of the file:
#include "flutter_window.h"
#include <optional>
#include "flutter/generated_plugin_registrant.h"
+#include "desktop_multi_window/desktop_multi_window_plugin.h"- Register the callback in the
OnCreate()method:
RegisterPlugins(flutter_controller_->engine());
+ DesktopMultiWindowSetWindowCreatedCallback([](void *controller) {
+ auto *flutter_view_controller =
+ reinterpret_cast<flutter::FlutterViewController *>(controller);
+ auto *registry = flutter_view_controller->engine();
+ RegisterPlugins(registry);
+ });
SetChildContent(flutter_controller_->view()->GetNativeWindow());The RegisterPlugins function will automatically register all plugins for each new window.
Edit macos/Runner/MainFlutterWindow.swift:
- Add the import at the top of the file:
import Cocoa
import FlutterMacOS
+import desktop_multi_window- Register the callback in the
awakeFromNib()method:
RegisterGeneratedPlugins(registry: flutterViewController)
+ FlutterMultiWindowPlugin.setOnWindowCreatedCallback { controller in
+ // Register the plugin which you want access from other isolate.
+ RegisterGeneratedPlugins(registry: controller)
+ }
+
super.awakeFromNib()The RegisterGeneratedPlugins function will automatically register all plugins for each new window.
Edit linux/my_application.cc:
- Add the include at the top of the file:
#include "my_application.h"
#include <flutter_linux/flutter_linux.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#include "flutter/generated_plugin_registrant.h"
+#include "desktop_multi_window/desktop_multi_window_plugin.h"- Register the callback in the
my_application_activate()function:
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
+ desktop_multi_window_plugin_set_window_created_callback([](FlPluginRegistry* registry){
+ fl_register_plugins(registry);
+ });
+
gtk_widget_grab_focus(GTK_WIDGET(view));The fl_register_plugins function will automatically register all plugins for each new window.
This plugin works great with window_manager to control window properties:
by now, you should this fork version with a bit fix
window_manager:
git:
url: https://github.com/boyan01/window_manager.git
path: packages/window_manager
ref: 6fae92d21b4c80ce1b8f71c1190d7970cf722bd4import 'package:window_manager/window_manager.dart';
// Configure window options
WindowOptions windowOptions = const WindowOptions(
size: Size(800, 600),
center: true,
backgroundColor: Colors.transparent,
skipTaskbar: false,
titleBarStyle: TitleBarStyle.hidden,
);
windowManager.waitUntilReadyToShow(windowOptions, () async {
await windowManager.show();
await windowManager.focus();
});
// Prevent window from closing immediately
windowManager.setPreventClose(true);
windowManager.addListener(this); // Must implement WindowListenerCheck out the example directory for a complete working application that demonstrates:
- Creating multiple window types
- Single instance vs multi-instance windows
- Communication between windows
- Custom window extensions
- Plugin registration for video playback
- Window lifecycle management
MIT