Skip to content

WindowFullscreen

View raw .md

Know whether the macOS window is fullscreen, follow it as it changes, and flip it with one call.

On this page

Basic Usage#

A fullscreen button that follows the window. ListenableBuilder adds and removes the listener itself, and the handler catches the one refusal a user can cause.

dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; // PlatformException
import 'package:magic_device/magic_device.dart';

Widget fullscreenButton() {
  if (!WindowFullscreen.instance.available) return const SizedBox.shrink();

  return ListenableBuilder(
    listenable: WindowFullscreen.instance,
    builder: (BuildContext context, Widget? child) => IconButton(
      icon: Icon(
        WindowFullscreen.instance.active
            ? Icons.fullscreen_exit
            : Icons.fullscreen,
      ),
      onPressed: () async {
        try {
          await WindowFullscreen.instance.toggle();
        } on PlatformException catch (error) {
          if (error.code != 'no_window') rethrow;
        }
      },
    ),
  );
}

Quick Reference#

Member Type Meaning
WindowFullscreen.instance static WindowFullscreen The app's one reader, made on first use. On macOS the first use reads the window once, so a window that opens already fullscreen is picked up.
available bool true on macOS only (never on web). Gate the control on it.
active bool Fullscreen, as the window last confirmed (AppKit's did-notification).
target bool Fullscreen or on its way there. Moves on the will-notification, ahead of active; the did-notification settles both.
transitioning bool Between the will- and the did-notification.
toggle() Future<void> Asks the window to enter or leave fullscreen.
pressTimeout static const Duration 1 second.
resetInstance() static void Test-only: drops the shared reader.

Reading the State#

One state, two readings. target is where the window is going, and active is what it confirmed. transitioning covers the gap.

Moment active target transitioning
Windowed false false false
Entering, animation under way false true true
Fullscreen true true false
Leaving, animation under way true false true

Follow target to animate a layout with the window, and active for what the window really is. During transitioning the window's size changes on every frame, so hold off size-sensitive work.

Toggling#

toggle() is a request, not a guarantee.

  • It is ignored while a press or a transition is under way, so a double press cannot undo itself.
  • It throws a PlatformException with code no_window when the Flutter view is not in a window. That refusal releases the press, so catch it where a user can trigger it.
  • AppKit silently ignores the call for an app that is not frontmost and posts nothing. One second (pressTimeout) after the call returns, the window is read again and that reading ends the press. Treat a missing change as normal, not as an error.
  • Anywhere but macOS, toggle() sends nothing.

Following the Window#

The state follows the window, not the calls. The plugin forwards the will- and did-notifications for every change, so the green button, Esc and the Window menu notify listeners exactly as toggle() does, and listeners hear only real changes.

Gotchas#

Mistake Fix
Building a second WindowFullscreen There is no public constructor: the channel takes one handler. Use instance.
Disposing the shared instance from a view A view adds and removes a listener and never disposes it, or every other reader is left on a disposed notifier.
Showing a fullscreen control everywhere Gate it on available.
Animating the layout off active active changes only once the window lands. Follow target.
Reaching instance in a macOS test without the channel mock The first use reads the window over the channel. Mock magic_device/window and call resetInstance() afterwards; see Testing.
Editing MainFlutterWindow.swift to add a channel Not needed: the package's macOS plugin registers magic_device/window and finds the window on each call.
esc

Search index did not load.

No match for "".

Try a class like rounded-lg or a widget like WButton.