1+ import 'dart:async' ;
12import 'dart:io' ;
23
34import 'package:collection/collection.dart' ;
@@ -8,8 +9,11 @@ import 'package:commet/main.dart';
89import 'package:commet/utils/event_bus.dart' ;
910import 'package:flutter/services.dart' ;
1011import 'package:window_manager/window_manager.dart' ;
12+ import 'package:tray_manager/tray_manager.dart' ;
1113
1214class WindowManagement {
15+ static bool _isShuttingDown = false ;
16+
1317 static Future <void > init () async {
1418 if (! (PlatformUtils .isLinux || PlatformUtils .isWindows)) return ;
1519
@@ -24,11 +28,54 @@ class WindowManagement {
2428 EventBus .onSelectedRoomChanged.stream.listen (_onSelectedRoomChanged);
2529 EventBus .onSelectedSpaceChanged.stream.listen (_onSelectedSpaceChanged);
2630
31+ _registerProcessSignalHandlers ();
32+
33+ await _initTrayManager ();
34+ TrayManager .instance.addListener (_TrayListener ());
35+
2736 if (commandLineArgs.contains ("--minimize" )) {
2837 windowManager.minimize ();
2938 }
3039 }
3140
41+ static void _registerProcessSignalHandlers () {
42+ ProcessSignal .sigint.watch ().listen ((_) {
43+ _shutdownApplication ();
44+ });
45+
46+ ProcessSignal .sigterm.watch ().listen ((_) {
47+ _shutdownApplication ();
48+ });
49+ }
50+
51+ static Future <void > _shutdownApplication () async {
52+ if (_isShuttingDown) return ;
53+ _isShuttingDown = true ;
54+
55+ if (clientManager != null ) {
56+ for (var client in clientManager! .clients) {
57+ await client.close ();
58+ }
59+ }
60+
61+ exit (0 );
62+ }
63+
64+ static Future <void > _initTrayManager () async {
65+ await TrayManager .instance.setIcon ('assets/images/app_icon/app_icon_rounded.png' );
66+ await _setupTrayMenu ();
67+ }
68+
69+ static Future <void > _setupTrayMenu () async {
70+ final menu = [
71+ MenuItem (label: 'Commet' , key: 'app_name' , disabled: true ),
72+ MenuItem .separator (),
73+ MenuItem (label: 'Open Commet' , key: 'show' ),
74+ MenuItem (label: 'Quit Commet' , key: 'close' ),
75+ ];
76+ await TrayManager .instance.setContextMenu (Menu (items: menu));
77+ }
78+
3279 static bool _onKeyEvent (KeyEvent event) {
3380 if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey .f11) {
3481 _toggleFullscreen ();
@@ -71,15 +118,41 @@ class _WindowListener extends WindowListener {
71118 super .onWindowClose ();
72119
73120 if (preferences.minimizeOnClose.value) {
74- windowManager.minimize ();
121+ windowManager.hide ();
75122 } else {
76- if (clientManager != null ) {
77- for (var client in clientManager! .clients) {
78- await client.close ();
79- }
80- }
123+ await WindowManagement ._shutdownApplication ();
124+ }
125+ }
126+ }
127+
128+ class _TrayListener extends TrayListener {
129+ @override
130+ void onTrayIconMouseDown () {
131+ _showWindow ();
132+ }
81133
82- exit (0 );
134+ @override
135+ void onTrayMenuItemClick (MenuItem menuItem) {
136+ switch (menuItem.key) {
137+ case 'show' :
138+ _showWindow ();
139+ break ;
140+ case 'close' :
141+ _closeApplication ();
142+ break ;
83143 }
84144 }
145+
146+ Future <void > _showWindow () async {
147+ if (await windowManager.isVisible ()) {
148+ await windowManager.focus ();
149+ } else {
150+ await windowManager.show ();
151+ await windowManager.focus ();
152+ }
153+ }
154+
155+ Future <void > _closeApplication () async {
156+ await WindowManagement ._shutdownApplication ();
157+ }
85158}
0 commit comments