Skip to content

About

The window_manager plugin provides comprehensive window management capabilities for Flutter desktop applications, enabling full control over window size, position, appearance, close behavior, and listening to events.

Topics

Resources

Stars

848 stars

Watchers

9 watching

Forks

Repository files navigation

window_manager is built on nativeapi, a Flutter binding of one C++ core library (libnativeapi/nativeapi) shared by macOS, Windows and Linux. Coming from 0.5.x? See Upgrading from 0.5.x.

window_manager

pub version All Contributors

This package lets Flutter desktop apps size, move, show, hide and decorate their own window.

English | 简体中文


Platform Support

Linux macOS Windows
✔️ ✔️ ✔️

Quick Start

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  window_manager: ^0.6.0

Or

dependencies:
  window_manager:
    git:
      url: https://github.com/leanflutter/window_manager.git
      ref: main

Requirements

  • Flutter 3.47 / Dart 3.13 or later, macOS 10.15 or later.
  • Linux build machines need GTK 3, X11 and Xi development files:
sudo apt-get install libgtk-3-dev libx11-dev libxi-dev

Usage

import 'package:window_manager/window_manager.dart';

final window = WindowManager.instance.getCurrent()!;

window.title = 'window_manager';
window.setSize(const Size(1000, 700).toNative(), false);
window.minimumSize = const Size(640, 480).toNative();
window.center();
window.show();

// Every window event of every window of this app.
WindowManager.instance.addListener((event) {
  switch (event) {
    case WindowFocusedEvent():
      debugPrint('window ${event.windowId} focused');
    case WindowResizedEvent():
      debugPrint('window ${event.windowId} is now ${event.newSize.toSize()}');
    default:
      break;
  }
});

// Ask before this window closes, however the user closes it. Close requests
// reach only the window's own listeners.
window.addListener((event) async {
  if (event is WindowCloseRequestedEvent && !await confirmClose()) {
    event.request.cancel();
  }
});

Window takes and returns nativeapi's Size, Point, Rectangle and Color, which are not exported because Flutter has its own: toNative() turns Flutter's into them, and toSize(), toOffset(), toRect() and toColor() turn them back.

With Flutter's multi-window API, package:window_manager/windowing.dart answers the Window behind each of Flutter's window controllers:

import 'package:window_manager/windowing.dart';

final window = controller.nativeWindow; // or nativeWindowOf(controller)
window?.title = 'Inspector';

A window with no title bar of its own, dragged and resized by widgets:

final window = WindowManager.instance.getCurrent()!;
window.titleBarStyle = TitleBarStyle.hidden;

// In the app:
DragToResizeArea(
  child: Column(
    children: [
      WindowCaption(
        brightness: Theme.of(context).brightness,
        title: const Text('window_manager'),
      ),
      Expanded(child: body),
    ],
  ),
)

The example app of this plugin covers the 0.5.x compatible API. For the full example — several windows at once, parent and child windows, every native property — see nativeapi's window_example.

Upgrading from 0.5.x

Code written for window_manager 0.5.x keeps working by importing package:window_manager/legacy.dart instead of package:window_manager/window_manager.dart. It provides the old windowManager, WindowListener, WindowOptions and calcWindowPosition on top of the native API.

The import has to change on purpose: legacy.dart is a bridge, not the future of this package. Its classes are marked @Deprecated and will be removed in a later release — move to the native API above when you can.

import 'package:window_manager/legacy.dart';

await windowManager.ensureInitialized();
await windowManager.waitUntilReadyToShow(
  const WindowOptions(size: Size(1000, 700), center: true),
  () async {
    await windowManager.show();
    await windowManager.focus();
  },
);

What differs from 0.5.x:

  • Builds need Flutter 3.47 / Dart 3.13 and macOS 10.15 (0.5.x: Flutter 3.3, macOS 10.11), and no longer need the plugin's own setup in MainFlutterWindow.swift, my_application.cc or the Windows runner — there is no platform plugin code left.
  • close(), destroy() and setPreventClose() behave as before: with setPreventClose(true) the title bar's close button and close() report onWindowClose and leave the window open, and destroy() closes it anyway. Closing the last window ends the app, as the platform's runner decides.
  • onWindowResized and onWindowMoved arrive together with onWindowResize and onWindowMove: nativeapi reports one event per change, not a stream and a final one.
  • Aero-snap docking is gone: isDockable() answers false, isDocked() null, dock() does nothing, undock() answers false, and onWindowDocked / onWindowUndocked never fire. grabKeyboard() / ungrabKeyboard() (Linux) are gone the same way.
  • popUpWindowMenu() opens the system menu at the cursor on Windows and on Linux window managers that have one, and does nothing on macOS.
  • forward of setIgnoreMouseEvents keeps hover events where the platform can (macOS, Windows and X11); elsewhere the window ignores the mouse without them.
  • Arguments the core library has no use for are accepted and ignored: vertically of maximize, animate of setPosition and setBounds, visibleOnFullScreen of setVisibleOnAllWorkspaces.
  • getId() answers nativeapi's own window id, not the NSWindow number or the HWND.
  • setAsFrameless() hides the title bar and its buttons; it no longer removes the window's border.
  • setAlignment handles any Alignment, not only the nine constants.
  • WindowCaption's close button closes the window, through its close listeners, so setPreventClose holds for it too. On Windows 11 its maximize button opens the snap layouts.
  • startDragging() and startResizing() are no longer skipped on Windows while the window is in full screen: the compatibility layer keeps no Platform branch of its own, the core library decides.
  • screen_retriever and path are no longer dependencies.
  • New example on package:flutter/widgets.dart alone; the full one is nativeapi's window_example.

Moving to the native API

0.5.x (legacy.dart) Native API (window_manager.dart)
windowManager (the app's one window) WindowManager.instance.getCurrent() — or get(id), getAll(), getWindowAtPoint(); every window is a Window of its own
await windowManager.getSize(), setSize(size) window.size.toSize(), window.setSize(size.toNative(), animate) — synchronous, no await
getBounds() / setBounds(rect) window.bounds.toRect(), window.bounds = rect.toNative(); window.contentBounds for the area without decorations
getPosition() / setPosition(offset) window.position.toOffset(), window.position = offset.toNative()
setMinimumSize / setMaximumSize / setAspectRatio window.minimumSize, window.maximumSize, window.aspectRatio
show() / show(inactive: true) / hide() window.show() / window.showInactive() / window.hide()
focus(), blur(), isFocused() window.focus(), window.blur(), window.isFocused
maximize(), unmaximize(), minimize(), restore() the same names on window, without await
setFullScreen(bool) / isFullScreen() window.isFullScreen
setResizable, setMovable, setMinimizable, setMaximizable, setClosable window.isResizable, isMovable, isMinimizable, isMaximizable, isClosable — also isFullScreenable
setAlwaysOnTop / setAlwaysOnBottom window.isAlwaysOnTop / window.isAlwaysOnBottom
setSkipTaskbar(true) window.isVisibleInTaskbar = false
setTitle / getTitle window.title
setTitleBarStyle(style, windowButtonVisibility:) window.titleBarStyle, window.isWindowControlButtonsVisible — also setTitleBarColors()
setHasShadow, setOpacity, setBackgroundColor window.hasShadow, window.opacity, window.backgroundColor — also window.visualEffect
setIgnoreMouseEvents(ignore, forward:) window.setIgnoreMouseEvents(ignore, forward)
close() / destroy() window.close(), which asks the window's close listeners first
setPreventClose(true) with onWindowClose window.addListener((event) { if (event is WindowCloseRequestedEvent) event.request.cancel(); })
popUpWindowMenu() window.showSystemMenu(position) — Window.isSystemMenuSupported() says where it works
setVisibleOnAllWorkspaces(bool) window.isVisibleOnAllWorkspaces
startDragging() / startResizing(edge) the same names on window; DragToMoveArea and DragToResizeArea call them for you
setProgressBar, setBadgeLabel, setIcon, setBrightness Application.instance — they belong to the app, not to one window
WindowListener window.addListener((event) { switch (event) { case WindowFocusedEvent(): … } }) for one window, WindowManager.instance.addListener for all — also WindowBlurredEvent, WindowMinimizedEvent, WindowMaximizedEvent, WindowRestoredEvent, WindowMovedEvent, WindowResizedEvent, WindowEnteredFullScreenEvent, WindowExitedFullScreenEvent, WindowCreatedEvent, WindowClosedEvent
calcWindowPosition(size, alignment) DisplayManager.instance — getAll(), getPrimary(), getCursorPosition(), and each Display's workArea

waitUntilReadyToShow, ensureInitialized, setAsFrameless and getDevicePixelRatio have no native counterpart: set the properties you want and call window.show() when you are ready.

Articles

Who's using it?

  • AuthPass - Password Manager based on Flutter for all platforms. Keepass 2.x (kdbx 3.x) compatible.
  • Biyi (比译) - A convenient translation and dictionary app written in dart / Flutter.
  • BlueBubbles - BlueBubbles is an ecosystem of apps bringing iMessage to Android, Windows, and Linux
  • LunaSea - A self-hosted controller for mobile and macOS built using the Flutter framework.
  • Linwood Butterfly - Open source note taking app written in Flutter
  • RustDesk - Yet another remote desktop software, written in Rust. Works out of the box, no configuration required.
  • Ubuntu Desktop Installer - This project is a modern implementation of the Ubuntu Desktop installer.

API

Native API

window_manager now re-exports the windowing APIs of nativeapi — Window, WindowManager, TitleBarStyle, ResizeEdge, VisualEffect, the window events with EventRequest for answering a close, and from nativeapi_flutter the DragToMoveArea, DragToResizeArea and MaximizeButtonArea widgets and the type conversions — alongside its own WindowCaption, WindowCaptionButton and VirtualWindowFrame. Import package:window_manager/legacy.dart only for code that still uses the 0.5.x API.

Contributors

LiJianying
LiJianying

💻
 A Arif A S
A Arif A S

💻
J-P Nurmi
J-P Nurmi

💻
Dixeran
Dixeran

💻
nikitatg
nikitatg

💻
Kristen McWilliam
Kristen McWilliam

💻
Kingtous
Kingtous

💻
Prome
Prome

💻
Bin
Bin

💻
youxiachai
youxiachai

💻
Allen Xu
Allen Xu

💻
CodeDoctor
CodeDoctor

💻
Jean-Christophe Binet
Jean-Christophe Binet

💻
Jon Salmon
Jon Salmon

💻
Karol Wrótniak
Karol Wrótniak

💻
LAIIIHZ
LAIIIHZ

💻
Mikhail Kulesh
Mikhail Kulesh

💻
Prateek Sunal
Prateek Sunal

💻
Ricardo Boss
Ricardo Boss

💻
Add your contributions

License

MIT

About

The window_manager plugin provides comprehensive window management capabilities for Flutter desktop applications, enabling full control over window size, position, appearance, close behavior, and listening to events.

Topics

Resources

Stars

848 stars

Watchers

9 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages