Coder Social home page Coder Social logo

zonble / flutter_window_close Goto Github PK

View Code? Open in Web Editor NEW
41.0 6.0 16.0 85.9 MB

Helps your Flutter apps to handle window close events.

Home Page: https://pub.dev/packages/flutter_window_close

License: MIT License

Dart 18.70% CMake 23.97% C++ 42.31% C 3.67% Swift 3.35% Ruby 2.85% HTML 5.16%
flutter flutter-plugin flutter-desktop

flutter_window_close's Introduction

flutter_window_close

2021 © Weizhong Yang a.k.a zonble

Pub example workflow License: MIT

flutter_window_close lets your Flutter app has a chance to confirm if the user wants to close your app. It works on desktop platforms including Windows, macOS and Linux.

macOS Windows Linux

Example

Getting Started

It is very common that an app would prompt a message like "Do you really want to quit" when users click on the close button, in order to notify that there are still undone tasks and the users may lose their data if they want to quit anyway. It prevents the users from losing data unwillingly.

To let a Flutter desktop app to support that, the plug-in listens to the events from the window hosting Flutter's view, and send the events to Flutter. What you need to do is to assign an anonymous function that can answer if the window should be closed. For example, you can show an alert dialog to ask what the current user is willing to do:

FlutterWindowClose.setWindowShouldCloseHandler(() async {
    return await showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
          title: const Text('Do you really want to quit?'),
          actions: [
            ElevatedButton(
            onPressed: () => Navigator.of(context).pop(true),
            child: const Text('Yes')),
            ElevatedButton(
            onPressed: () => Navigator.of(context).pop(false),
            child: const Text('No')),
          ]);
        });
});

The plugin bridges following APIs:

It does not support mobile platforms, since there is no such event for closing windows. You can use a custom WillPopScope to capture if a user is leaving your app with a back key.

macOS

There could be some issues while using the package on macOS. Each platform has its paradigm and the developer framework macOS sees window objects in a different way from Windows and Linux.

On Windows and Linux, windows are more like controllers in MVC pattern , and when it comes to Flutter, there would be always a root window in the process of an app, and our plugin could easily know which is the window to listen to. In the code level, we use GetActiveWindow while we can use gtk_widget_get_ancestor or gtk_widget_get_toplevel.

On the contrary, windows are more like views on macOS. An app can have multiple windows, and the app can stay still open event all windows are closed. We can also create an object with multiple IBOutlets to multiple windows. Flutter macOS does not tell plugins which window is the one running Flutter as well.

The plugin listens to the first window in the windows list of the singleton NSApplication object. It works if you have only one window in your macOS Flutter app. If you just create a new app using the official template for macOS, you may need not to change anything. However, if your app has multiple windows, the behavior of the plugin might be unexpectable.

Flutter Web

We can do little when a user is closing the tab or window hosting your Flutter Web app. The only way to let a user to confirm if he or she really want to close is to set the return value of the onbeforeunload event. You can use the setWebReturnValue method to set the return value.

License

The package is released under MIT license.

flutter_window_close's People

Contributors

alexmercerind avatar doppio avatar zonble avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

flutter_window_close's Issues

Windows platform not working

I've added the following code to my application

@override
  void initState() {
    super.initState();

    if (kIsWeb) {
      FlutterWindowClose.setWebReturnValue('Are you sure?');
      return;
    }

    FlutterWindowClose.setWindowShouldCloseHandler(() async {
      if (_alertShowing) return false;
      _alertShowing = true;

      return await showDialog(
          context: context,
          builder: (context) {
            return AlertDialog(
                title: const Text('Do you really want to quit?'),
                actions: [
                  ElevatedButton(
                      onPressed: () {
                        Navigator.of(context).pop(true);
                        _alertShowing = false;
                      },
                      child: const Text('Yes')),
                  ElevatedButton(
                      onPressed: () {
                        Navigator.of(context).pop(false);
                        _alertShowing = false;
                      },
                      child: const Text('No'))
                ]);
          });
    });
  }

This works on macOS, but on not on Windows. When I click exit button on the top right of the window, the application quits right away.

P.S. I've looked at the example project and it works on Windows, however when I copy the exact same code into a new flutter project it does not work on Windows. I using the latest 0.2.2 version.

Does not work on Web.

On pub.dev it says this package works on the web but throws an error "The method does not work in Flutter Web." at the top of the method "setWindowShouldCloseHandler". Please update the supported platforms removing "web" if it is not ready for the web.

Edit: Sorry, didn't notice the note about the "setWebReturnValue" method. I'm closing this issue.

Issue on Linux after a flutter upgrade

Hello,
I am using the package for a desktop app. I tested on linux and it seems that the flutter version 3.16.0 and even previous version (tested also in the 3.13.5) does not execute the callback.
It can be reproduced directly in with the example.

Linux with flutter 3.16.0

-> flutter run -d linux does not execute the callback when closing the app.

 flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.16.0, on Fedora Linux 37 (Workstation Edition) 6.5.8-100.fc37.x86_64, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Android Studio (version 2020.3)
[✓] VS Code (version 1.83.1)
[✓] Connected device (2 available)
[✓] Network resources

• No issues found!

In the log I can see that something went wrong :

(flutter_window_close_example:270572): Gdk-CRITICAL **: 11:04:02.969: gdk_window_get_state: assertion 'GDK_IS_WINDOW (window)' failed`

Linux with flutter 3.7.8

-> flutter run -d linux works just fine

flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.7.8, on Fedora Linux 37 (Workstation Edition) 6.5.8-100.fc37.x86_64, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Android Studio (version 2020.3)
[✓] VS Code (version 1.83.1)
[✓] Connected device (2 available)
[✓] HTTP Host Availability

• No issues found!

PlatformException(no_window, The active window does not exist, null, null)

Hello guys, I'm trying to execute the example but i get this error every time i click the close button.

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(no_window, The active window does not exist, null, null) #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:652:7) #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:310:18) <asynchronous suspension>

Do you have any suggestion?

Thanks a lot

Window won't close if not active on Windows (Win32)

Hello!

I noticed an unexpected behavior on your plugin while I was doing some research about window management on Flutter for Desktop: the window will not close if it's not active. That's due the call for GetActiveWindow() in the method call handler:

void FlutterWindowClosePlugin::HandleMethodCall(
const flutter::MethodCall<flutter::EncodableValue>& method_call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result)
{
if (method_call.method_name().compare("closeWindow") == 0) {
HWND handle = GetActiveWindow();
PostMessage(handle, WM_CLOSE, 0, 0);
result->Success(flutter::EncodableValue(nullptr));
} else if (method_call.method_name().compare("destroyWindow") == 0) {
HWND handle = GetActiveWindow();
DestroyWindow(handle);
result->Success(flutter::EncodableValue(nullptr));
} else {
result->NotImplemented();
}
}

I tested Linux as well, only Windows showed that behavior. I couldn't test MacOS.

A motivating use case would be prompting the user before closing the window but having a timeout for its reaction. The clip below illustrates that idea and shows how the window won't close after the timeout (5s) if the user is interacting with other window at that moment. Just two additions to your example/lib/main.dart will reproduce the scenario shown in the videoclip.

diff --git a/example/lib/main.dart b/example/lib/main.dart
index 6741910..17fd6bf 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -75,6 +75,7 @@ class _MainPageState extends State<MainPage> {
             builder: (context) {
               return AlertDialog(
                   title: const Text('Do you really want to quit?'),
+                  content: const Text('This will close in a few seconds if you do not hit the "No" button.'),
                   actions: [
                     ElevatedButton(
                         onPressed: () {
@@ -89,7 +90,7 @@ class _MainPageState extends State<MainPage> {
                         },
                         child: const Text('No'))
                   ]);
-            });
+            }).timeout(const Duration(seconds: 5), onTimeout: () => true);
       } else if (_index == 1) {
         final result = await FlutterPlatformAlert.showCustomAlert(
           windowTitle: "Really?",
flutter_window_close_before.mp4

I forked your plugin and experimented a fix, should you be interested in it I can open a PR. The idea is basically never call GetActiveWindow(), use the Flutter API to register a WindProc delegate and finally, at the moment of the method call, get the parent window of the Flutter view, which can be made accessible by storing a pointer to the Registrar (most plugins do that). With that in place, even if the window is minimized it will exit after the timeout.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.