Skip to main content

flutter_second_screen 1.0.0 copy "flutter_second_screen: ^1.0.0" to clipboard
flutter_second_screen: ^1.0.0 copied to clipboard

A clean architecture Flutter package for managing secondary screens and cross-screen communication on Windows and macOS desktop, with upcoming Android and iOS support.

Flutter Second Screen #

A production-grade, Clean Architecture Flutter package for managing secondary screens, dual displays, and cross-screen communication. Currently available for Windows Desktop, with architectural blueprints and upcoming native support for Android and iOS.


๐ŸŒŸ Key Features #

  • Multi-Display Detection: Query physical monitors, detect primary vs. secondary displays, resolutions, and position offsets.
  • Secondary Window Lifecycle: Initialize, open, maximize, focus, and close secondary windows seamlessly.
  • Bi-Directional Messaging: Typed or event-based cross-screen event bus to transfer cart data, signatures, advertisements, or status updates between windows.
  • Clean Architecture & SOLID: Strict separation of concerns (Domain, Data, Presentation) with dependency inversion, interface segregation, and platform interface extensibility.
  • Developer-Friendly Mixin & Widgets: Use SecondScreenListenerMixin, SecondScreenEventListener, or SecondScreenEventBuilder for reactive UI updates without boilerplate.
  • Multi-Platform Blueprint: Built on Flutter's PlatformInterface standard with pluggable platform classes and documented TODO blueprints for Android Presentation API and iOS external UIScreen.

๐Ÿ–ฅ Platform Support #

Platform Support Status Underlying Mechanism
Windows Desktop / macOS โœ… Available window_manager_plus + screen_retriever multi-window
Android โณ In Development android.app.Presentation + DisplayManager
iOS โณ In Development UIScreen external displays + UIWindow
Linux ๐Ÿ“‹ Planned Desktop multi-window & display retriever

๐Ÿ› Architecture Overview #

graph TD
    subgraph UI ["Presentation Layer"]
        ScreenA["Main Screen View"]
        ScreenB["Secondary Screen View"]
        Mixin["SecondScreenListenerMixin"]
        Widget["SecondScreenEventListener"]
    end

    subgraph Facade ["Unified Facade"]
        FSS["FlutterSecondScreen"]
    end

    subgraph Domain ["Domain Layer (Pure Dart)"]
        DM["SecondScreenDisplayManager"]
        WM["SecondScreenWindowManager"]
        MS["SecondScreenMessenger"]
        Repo["SecondScreenRepository"]
        UseCases["Use Cases (Open, Close, Init, SendEvent, etc.)"]
        Entities["Entities (ScreenDisplay, SecondScreenEvent, SecondScreenConfig)"]
    end

    subgraph Data ["Data Layer"]
        RepoImpl["SecondScreenRepositoryImpl"]
        PI["SecondScreenPlatform (Interface)"]
        DeskPlat["DesktopSecondScreenPlatform"]
        WinPlat["WindowsSecondScreenPlatform"]
        MacPlat["MacosSecondScreenPlatform"]
        AndPlat["AndroidSecondScreenPlatform (TODO / Blueprint)"]
        IosPlat["IosSecondScreenPlatform (TODO / Blueprint)"]
    end

    UI --> Facade
    Facade --> UseCases
    UseCases --> Repo
    RepoImpl -.-> Repo
    RepoImpl --> PI
    PI <|-- DeskPlat
    DeskPlat <|-- WinPlat
    DeskPlat <|-- MacPlat
    PI <|-- AndPlat
    PI <|-- IosPlat

SOLID Principles Applied: #

  • Single Responsibility Principle (SRP): Display queries (SecondScreenDisplayManager), window lifecycle management (SecondScreenWindowManager), and inter-screen messaging (SecondScreenMessenger) are decoupled into focused, dedicated interfaces.
  • Open/Closed Principle (OCP): Adding support for a new operating system (e.g., Android, iOS, or macOS) only requires implementing SecondScreenPlatform without modifying the domain use cases or repository contracts.
  • Liskov Substitution Principle (LSP): Any platform implementation (WindowsSecondScreenPlatform, AndroidSecondScreenPlatform, or test mocks) can be seamlessly substituted without breaking consumers.
  • Interface Segregation Principle (ISP): Clients can depend solely on SecondScreenDisplayManager, SecondScreenWindowManager, or SecondScreenMessenger instead of one monolithic interface.
  • Dependency Inversion Principle (DIP): High-level application modules depend on domain abstractions rather than concrete platform libraries.

๐Ÿš€ Getting Started #

1. Add Dependency #

In your pubspec.yaml:

dependencies:
  flutter_second_screen: ^1.0.0

2. Main Entry Point Setup #

In your main.dart, handle the secondary screen entry point when the process is launched:

import 'package:flutter/material.dart';
import 'package:flutter_second_screen/flutter_second_screen.dart';

void main(List<String> args) async {
  WidgetsFlutterBinding.ensureInitialized();
  await FlutterSecondScreen.ensureInitialized(args);

  if (FlutterSecondScreen.isSecondaryScreen(args)) {
    // Secondary screen process
    final initialized = await FlutterSecondScreen.instance.initSecondaryDisplay(
      const SecondScreenConfig(title: 'Customer Facing Display'),
    );
    if (initialized) {
      runApp(const CustomerDisplayApp());
    }
  } else {
    // Main cashier / POS application
    runApp(const CashierMainApp());
  }
}

๐Ÿ’ก Usage Examples #

Opening the Secondary Screen #

final secondScreen = FlutterSecondScreen.instance;

// Check if a second physical monitor is connected
if (await secondScreen.isSecondaryDisplayAvailable()) {
  await secondScreen.openSecondaryScreen(arguments: ['second-screen']);
}

Sending Events Between Screens #

// Send from Main Screen to Secondary Screen
await secondScreen.sendEventToSecondary('cartUpdate', {
  'items': [
    {'name': 'Sneakers', 'price': 89.99},
  ],
  'total': 89.99,
});

// Send from Secondary Screen back to Main Screen (e.g. Signature or Confirmation)
await secondScreen.sendEventToMain('signatureApproved', signatureData);

Listening to Events with SecondScreenListenerMixin #

class CustomerDisplayScreen extends StatefulWidget {
  const CustomerDisplayScreen({super.key});

  @override
  State<CustomerDisplayScreen> createState() => _CustomerDisplayScreenState();
}

class _CustomerDisplayScreenState extends State<CustomerDisplayScreen>
    with SecondScreenListenerMixin {
  Map<String, dynamic>? cartData;

  @override
  Map<String, void Function(dynamic)> getSecondScreenEventListeners() {
    return {
      'cartUpdate': (data) {
        setState(() {
          cartData = data as Map<String, dynamic>;
        });
      },
      'reset': (_) {
        setState(() {
          cartData = null;
        });
      },
    };
  }

  @override
  Widget build(BuildContext context) {
    if (cartData == null) {
      return const Center(child: Text('Welcome!'));
    }
    return Text('Total: \$${cartData!['total']}');
  }
}

Listening to Events with SecondScreenEventListener Widget #

SecondScreenEventListener(
  eventName: 'cartUpdate',
  onEvent: (data) {
    debugPrint('Received cart update: $data');
  },
  child: const MyCartWidget(),
);

๐Ÿ“ฑ Upcoming Android & iOS Implementation #

flutter_second_screen defines clean platform contracts and architectural blueprints for Android and iOS in:

  • AndroidSecondScreenPlatform (lib/src/data/datasources/android_second_screen_platform.dart)
  • IosSecondScreenPlatform (lib/src/data/datasources/ios_second_screen_platform.dart)

Android Roadmap #

  • Integrates with Android's DisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION).
  • Spawns a secondary FlutterEngine inside an android.app.Presentation dialog window.
  • Communicates across engines via native MethodChannel and EventChannel.

iOS Roadmap #

  • Detects external displays via UIScreen.screens and UIScreenDidConnectNotification.
  • Attaches a secondary UIWindow with a FlutterViewController bound to the external UIScreen.
  • Communicates across engines via native MethodChannel and EventChannel.

๐Ÿงช Testing #

The package includes comprehensive unit and widget tests covering all entities, use cases, repository implementations, mixins, and platform interfaces:

cd packages/flutter_second_screen
flutter test

๐Ÿ“„ License #

This project is licensed under the MIT License - see the LICENSE file for details.

๐ŸŒŸ Support #

If you find this package helpful, please consider giving it a โญ on GitHub and a ๐Ÿ‘ on pub.dev!

0
likes
160
points
0
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A clean architecture Flutter package for managing secondary screens and cross-screen communication on Windows and macOS desktop, with upcoming Android and iOS support.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, plugin_platform_interface, screen_retriever, window_manager_plus

More

Packages that depend on flutter_second_screen

Packages that implement flutter_second_screen