window_manager

repository·main·Indexed 21 days ago

https://github.com/leanflutter/window_manager

A Flutter plugin for comprehensive window management in desktop applications on Linux, macOS, and Windows. It provides control over window size, position, appearance, and lifecycle events. Key features include the ability to hide title bars, create borderless windows, implement custom close handlers, and use specialized widgets like DragToMoveArea, DragToResizeArea, VirtualWindowFrame, and WindowCaption to simulate native window behaviors.

Tokens
5.3K
Snippets
18
Records
25
Agent score
74%

What's inside window_manager

  1. Overview of window_manager capabilities

    main

    The window_manager plugin provides comprehensive window management for Flutter desktop applications. It allows developers to control window dimensions, positioning, appearance, and lifecycle events.

    Key capabilities include:

    • Window Control: Setting size, minimum/maximum limits, positioning windows across displays, and managing states like maximize, minimize, or fullscreen. It also supports custom close handlers.
    • Visual Customization: Hiding title bars, creating borderless windows, adjusting opacity/background color, and controlling window shadows.
    • Event Listeners: Monitoring lifecycle events (open/close), state changes (maximize/minimize/fullscreen), position changes (move/resize), and focus changes (focus/blur).
  2. Hide window at launch (Linux, macOS, Windows)

    main

    To avoid showing an unstyled window during Flutter startup, you can hide the window at the native level and only show it once Flutter is ready.

    Linux

    In linux/my_application.cc, replace gtk_widget_show(GTK_WIDGET(window)) with gtk_widget_realize(GTK_WIDGET(window)).

    macOS

    In macos/Runner/MainFlutterWindow.swift, override order(_:relativeTo:) to call hiddenWindowAtLaunch().

    Windows

    For older projects, in windows/runner/win32_window.cpp, remove the WS_VISIBLE flag from CreateWindow.

    For newer Flutter (3.7+) projects, in windows/runner/flutter_window.cpp, comment out or delete this->Show() inside the SetNextFrameCallback.

    Note: When using this pattern, ensure you call setState(() {}) inside your onWindowFocus listener to trigger the UI render once the window becomes visible.

  3. Disable QuitOnClose on macOS

    main

    If you intend to use the hide method on macOS, you must prevent the application from terminating after the last window is closed. Modify macos/Runner/AppDelegate.swift to return false in applicationShouldTerminateAfterLastWindowClosed.

    import Cocoa
    import FlutterMacOS
    
    @NSApplicationMain
    class AppDelegate: FlutterAppDelegate {
      override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
        return false
      }
    }
  4. Initialize and configure window_manager in main()

    main

    To manage windows, you must initialize the plugin within your main() function. Use windowManager.ensureInitialized() after ensuring Flutter bindings are initialized. You can then use windowManager.waitUntilReadyToShow() to apply WindowOptions (such as size, centering, and title bar style) before showing and focusing the window.

    import 'package:flutter/material.dart';
    import 'package:window_manager/window_manager.dart';
    
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      // Must add this line.
      await windowManager.ensureInitialized();
    
      WindowOptions windowOptions = 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();
      });
    
      runApp(MyApp());
    }
  5. Implement 'Confirm before closing' dialog

    main

    To intercept the window close event and show a confirmation dialog, use windowManager.setPreventClose(true). In your onWindowClose callback, check windowManager.isPreventClose() and, if true, show your dialog. If the user confirms, call windowManager.destroy() to close the window.

      void _init() async {
        // Add this line to override the default close handler
        await windowManager.setPreventClose(true);
        setState(() {});
      }
    
      @override
      void onWindowClose() async {
        bool _isPreventClose = await windowManager.isPreventClose();
        if (_isPreventClose) {
          showDialog(
            context: context,
            builder: (_) {
              return AlertDialog(
                title: Text('Are you sure you want to close this window?'),
                actions: [
                  TextButton(
                    child: Text('No'),
                    onPressed: () => Navigator.of(context).pop(),
                  ),
                  TextButton(
                    child: Text('Yes'),
                    onPressed: () async {
                      Navigator.of(context).pop();
                      await windowManager.destroy();
                    },
                  ),
                ],
              );
            },
          );
        }
      }
  6. Handle window close events and prevention

    main

    You can intercept the native close signal to perform cleanup or show a confirmation dialog.

    1. Use setPreventClose(true) to tell the native side to wait for your app's signal.
    2. Listen for the close event via a WindowListener.
    3. Call windowManager.close() when you are ready to exit.

    Check isPreventClose() to see if the signal is currently being intercepted.

    await windowManager.setPreventClose(true);
    // Later, in your close logic:
    await windowManager.close();
  7. Initialize and use window_manager

    main

    To use window_manager, you must first ensure the Flutter bindings are initialized and then call windowManager.ensureInitialized().

    You can then use WindowOptions to configure the window's initial state (size, centering, background color, etc.) and use waitUntilReadyToShow to safely show and focus the window once it is ready.

    import 'package:flutter/material.dart';
    import 'package:window_manager/window_manager.dart';
    
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      // Must include this line.
      await windowManager.ensureInitialized();
    
      WindowOptions windowOptions = 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();
      });
    
      runApp(MyApp());
    }
  8. Listen to window events with WindowListener

    main

    To respond to window lifecycle changes (like resizing, moving, or focusing), implement the WindowListener mixin on your State class. Register the listener using windowManager.addListener(this) in initState and unregister it using windowManager.removeListener(this) in dispose.

    Available callbacks include:

    • onWindowEvent(String eventName)
    • onWindowClose()
    • onWindowFocus()
    • onWindowBlur()
    • onWindowMaximize()
    • onWindowUnmaximize()
    • onWindowMinimize()
    • onWindowRestore()
    • onWindowResize()
    • onWindowMove()
    • onWindowEnterFullScreen()
    • onWindowLeaveFullScreen()
    import 'package:flutter/cupertino.dart';
    import 'package:window_manager/window_manager.dart';
    
    class HomePage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> with WindowListener {
      @override
      void initState() {
        super.initState();
        windowManager.addListener(this);
      }
    
      @override
      void dispose() {
        windowManager.removeListener(this);
        super.dispose();
      }
    
      @override
      void onWindowClose() {
        // do something
      }
    
      @override
      void onWindowFocus() {
        // do something
      }
    
      // ... other callbacks
    }