macos_window_toolkit 1.1.3 copy "macos_window_toolkit: ^1.1.3" to clipboard
macos_window_toolkit: ^1.1.3 copied to clipboard

Flutter plugin for macOS window management - retrieve window info, monitor permissions, and interact with system windows.

macOS Window Toolkit #

pub package License: MIT

A Flutter plugin for macOS that provides comprehensive window management functionality. This plugin allows Flutter applications to retrieve detailed information about all open windows on the macOS system, including window properties like title, bounds, owner application, and process ID.

Features #

  • πŸͺŸ Window Enumeration: Get a list of all open windows on the system
  • πŸ“Š Window Properties: Access detailed window information including:
    • Window ID and title
    • Owner application name
    • Window bounds (position and size)
    • Window layer level
    • Visibility status
    • Process ID
  • πŸ‘€ Real-time Permission Monitoring: Monitor macOS permissions with live updates
    • Screen Recording permission tracking
    • Accessibility permission tracking
    • Configurable monitoring intervals
    • Type-safe permission status updates
    • Perfect integration with state management (Riverpod, Bloc, etc.)
  • πŸ” Permission Management: Check and request macOS permissions
    • Screen recording permission
    • Accessibility permission
    • Open system preference panes
  • πŸš€ High Performance: Efficient native implementation using Core Graphics APIs
  • πŸ›‘οΈ Privacy Compliant: Includes proper privacy manifest for App Store distribution
  • πŸ”§ Easy Integration: Simple API with comprehensive error handling

Platform Support #

Platform Support
macOS βœ…
iOS ❌
Android ❌
Windows ❌
Linux ❌
Web ❌

Minimum Requirements:

  • macOS 10.11 or later
  • Flutter 3.3.0 or later
  • Dart 3.8.1 or later

Installation #

Add this package to your pubspec.yaml:

dependencies:
  macos_window_toolkit: ^1.1.3

Then run:

flutter pub get

Quick Start #

Basic Window Enumeration #

import 'package:macos_window_toolkit/macos_window_toolkit.dart';

void main() async {
  final toolkit = MacosWindowToolkit();
  
  // Get all open windows
  final windows = await toolkit.getAllWindows();
  
  for (final window in windows) {
    print('Window: ${window.name}');
    print('App: ${window.ownerName}');
    print('Bounds: ${window.bounds}');
    print('---');
  }
}

Real-time Permission Monitoring #

import 'package:macos_window_toolkit/macos_window_toolkit.dart';

void main() async {
  final toolkit = MacosWindowToolkit();
  
  // Start monitoring permissions every 2 seconds
  toolkit.startPermissionWatching();
  
  // Listen to permission changes
  toolkit.permissionStream.listen((status) {
    if (status.hasChanges) {
      print('Permission changed!');
      print('Screen Recording: ${status.screenRecording}');
      print('Accessibility: ${status.accessibility}');
      
      if (status.allPermissionsGranted) {
        print('All permissions granted! πŸŽ‰');
      } else {
        print('Missing: ${status.deniedPermissions.join(', ')}');
      }
    }
  });
}

Usage #

Permission Monitoring with Riverpod #

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:macos_window_toolkit/macos_window_toolkit.dart';

// Create a StreamProvider for permission monitoring
final permissionProvider = StreamProvider<PermissionStatus>((ref) {
  final toolkit = MacosWindowToolkit();
  toolkit.startPermissionWatching(
    interval: const Duration(seconds: 2),
    emitOnlyChanges: true, // Only emit when permissions change
  );
  return toolkit.permissionStream;
});

// Use in your widget
class MyApp extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final permissionAsync = ref.watch(permissionProvider);
    
    return permissionAsync.when(
      data: (status) {
        if (status.allPermissionsGranted) {
          return MainApp(); // Show main app
        } else {
          return PermissionSetupScreen(
            missingPermissions: status.deniedPermissions,
          );
        }
      },
      loading: () => const LoadingScreen(),
      error: (error, _) => ErrorScreen(error: error),
    );
  }
}

Basic Window Enumeration #

import 'package:macos_window_toolkit/macos_window_toolkit.dart';

class WindowManager {
  final _toolkit = MacosWindowToolkit();
  
  Future<List<MacosWindowInfo>> getVisibleWindows() async {
    try {
      final windows = await _toolkit.getAllWindows();
      return windows.where((window) => window.isOnScreen).toList();
    } catch (e) {
      print('Error getting windows: $e');
      return [];
    }
  }
}

Permission Management #

final toolkit = MacosWindowToolkit();

// Check current permissions
final hasScreenRecording = await toolkit.hasScreenRecordingPermission();
final hasAccessibility = await toolkit.hasAccessibilityPermission();

// Request permissions
await toolkit.requestScreenRecordingPermission();
await toolkit.requestAccessibilityPermission();

// Open system settings
await toolkit.openScreenRecordingSettings();
await toolkit.openAccessibilitySettings();

Window Information Structure #

Each window object contains the following properties:

class WindowInfo {
  final int windowId;        // Unique window identifier
  final String name;         // Window title
  final String ownerName;    // Application name that owns the window
  final List<double> bounds; // [x, y, width, height]
  final int layer;           // Window layer level
  final bool isOnScreen;     // Whether window is visible
  final int processId;       // Process ID of the owning application
}

Filtering Windows #

// Filter by application
final chromeWindows = windows
    .where((w) => w.ownerName.contains('Chrome'))
    .toList();

// Filter by visibility
final visibleWindows = windows
    .where((w) => w.isOnScreen)
    .toList();

// Filter by size (width > 500px)
final largeWindows = windows
    .where((w) => w.bounds[2] > 500)
    .toList();

Error Handling #

try {
  final windows = await MacosWindowToolkit.getAllWindows();
  // Process windows
} on PlatformException catch (e) {
  switch (e.code) {
    case 'PERMISSION_DENIED':
      print('Permission denied to access window information');
      break;
    case 'SYSTEM_ERROR':
      print('System error occurred: ${e.message}');
      break;
    default:
      print('Unknown error: ${e.message}');
  }
} catch (e) {
  print('Unexpected error: $e');
}

Example App #

The plugin includes a comprehensive example app that demonstrates all features:

cd example/
flutter run -d macos

The example app includes:

  • Real-time window list updates
  • Window search and filtering
  • Detailed window information display
  • Permission handling examples

Privacy and Permissions #

This plugin uses public macOS APIs that typically don't require explicit user permissions. However, some system configurations might require accessibility permissions for full functionality.

App Sandbox Requirements #

Important: Applications using this plugin must disable App Sandbox to function properly. This is because the plugin requires access to system-wide resources that are restricted in sandboxed environments.

Why Sandbox Must Be Disabled

The plugin uses the following APIs that require sandbox to be disabled:

  1. Window Information Access

    • CGWindowListCopyWindowInfo() - Accesses window data from other applications
    • Sandboxed apps cannot read window information from other processes
  2. Accessibility API Operations

    • AXUIElementCreateApplication() - Creates accessibility elements for other apps
    • AXUIElementCopyAttributeValue() - Reads window properties from other apps
    • AXUIElementPerformAction() - Performs actions (like closing windows) on other apps
  3. Process Control Operations

    • kill() system calls - Terminates other processes
    • sysctl() - Queries system process lists
    • NSRunningApplication - Controls other applications
  4. Screen Capture (Legacy Support)

    • CGWindowListCreateImage() - Captures screenshots of other app windows
    • Requires access to other applications' visual content
  5. Apple Events Communication

    • Requires com.apple.security.automation.apple-events entitlement
    • Enables inter-app communication for window management

How to Disable Sandbox

To disable sandbox in your macOS app:

  1. Open macos/Runner/Release.entitlements and macos/Runner/DebugProfile.entitlements
  2. Set the sandbox key to false:
<key>com.apple.security.app-sandbox</key>
<false/>
  1. Add Apple Events entitlement:
<key>com.apple.security.automation.apple-events</key>
<true/>

App Store Distribution

Note: Apps distributed through the Mac App Store typically require sandboxing. If you need App Store distribution, you may need to:

  • Request special entitlements from Apple for system-level access
  • Consider alternative approaches that work within sandbox restrictions
  • Distribute outside the App Store

Privacy Manifest #

The plugin includes a privacy manifest (PrivacyInfo.xcprivacy) that declares:

  • No user data collection
  • No tracking functionality
  • No network requests

API Reference #

MacosWindowToolkit #

The main class providing window management functionality.

Methods

getAllWindows()

Returns a list of all open windows on the system.

Returns: Future<List<WindowInfo>>

Throws: PlatformException if system error occurs

final windows = await MacosWindowToolkit.getAllWindows();

WindowInfo #

Data class representing a window's information.

Properties

Property Type Description
windowId int Unique system window identifier
name String Window title or name
ownerName String Name of the application that owns the window
bounds List<double> Window bounds as [x, y, width, height]
layer int Window layer level (higher = more front)
isOnScreen bool Whether the window is currently visible
processId int Process ID of the owning application

Performance Considerations #

  • Window enumeration is performed on-demand (not cached)
  • Each call returns fresh system data
  • Large numbers of windows may impact performance
  • Consider implementing pagination for apps with many windows

Troubleshooting #

Common Issues #

  1. Empty window list: Check if other applications have windows open
  2. Permission errors: Verify system accessibility permissions if needed
  3. Build errors: Ensure minimum macOS version requirements are met

Debug Mode #

Enable verbose logging for debugging:

flutter run -d macos --verbose

Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

Development Setup #

  1. Fork the repository
  2. Clone your fork
  3. Create a feature branch
  4. Make your changes
  5. Run tests: flutter test
  6. Submit a pull request

License #

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

Changelog #

See CHANGELOG.md for a detailed list of changes and version history.

Support #


Made with ❀️ for the Flutter community

1
likes
0
points
94
downloads

Publisher

unverified uploader

Weekly Downloads

Flutter plugin for macOS window management - retrieve window info, monitor permissions, and interact with system windows.

Repository (GitHub)
View/report issues

Topics

#macos #window-management #native-integration #screenshots #flutter-macos

Documentation

Documentation

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on macos_window_toolkit

Packages that implement macos_window_toolkit