@@ -148,8 +148,11 @@ class WindowHeader extends StatefulWidget {
148148class _WindowHeaderState extends State <WindowHeader > {
149149 final isMaximizedNotifier = ValueNotifier <bool >(false );
150150 final isPinNotifier = ValueNotifier <bool >(false );
151- bool _manualMaximized = false ; // Track manual maximized state on Windows
151+ bool _windowsBoundsMaximized =
152+ false ; // Track Windows-specific bounds-based maximize state
152153 Rect ? _savedBounds; // Save window bounds before maximizing
154+ bool _isUpdatingMaximized =
155+ false ; // Prevent concurrent maximize/unmaximize operations
153156
154157 @override
155158 void initState () {
@@ -170,53 +173,142 @@ class _WindowHeaderState extends State<WindowHeader> {
170173 }
171174
172175 Future <void > _updateMaximized () async {
173- final isMaximized = system.isWindows
174- ? _manualMaximized
175- : await windowManager.isMaximized ();
176-
177- if (isMaximized) {
178- // Unmaximize and restore previous size
179- if (system.isWindows && _savedBounds != null ) {
180- // Restore saved window bounds on Windows
181- await windowManager.setBounds (_savedBounds! );
182- _savedBounds = null ;
183- } else {
184- await windowManager.unmaximize ();
185- }
186- _manualMaximized = false ;
187- isMaximizedNotifier.value = false ;
188- } else {
189- // Maximize window
190- if (system.isWindows) {
191- // Save current window bounds
192- final currentPosition = await windowManager.getPosition ();
193- final currentSize = await windowManager.getSize ();
194- _savedBounds = Rect .fromLTWH (
195- currentPosition.dx,
196- currentPosition.dy,
197- currentSize.width,
198- currentSize.height,
199- );
200-
201- // On Windows, manually set to work area size (excluding taskbar)
202- final display = await screenRetriever.getPrimaryDisplay ();
203- final visiblePosition = display.visiblePosition ?? Offset .zero;
204- final visibleSize = display.visibleSize ?? display.size;
205-
206- await windowManager.setBounds (
207- Rect .fromLTWH (
208- visiblePosition.dx,
209- visiblePosition.dy,
210- visibleSize.width,
211- visibleSize.height,
212- ),
213- );
214- _manualMaximized = true ;
215- isMaximizedNotifier.value = true ;
176+ // Prevent concurrent execution to avoid race conditions
177+ if (_isUpdatingMaximized) return ;
178+ _isUpdatingMaximized = true ;
179+
180+ try {
181+ final isMaximized = system.isWindows
182+ ? _windowsBoundsMaximized
183+ : await windowManager.isMaximized ();
184+
185+ if (isMaximized) {
186+ // Unmaximize and restore previous size
187+ if (system.isWindows) {
188+ if (_savedBounds != null ) {
189+ // Restore saved window bounds if we have them
190+ try {
191+ await windowManager.setBounds (_savedBounds! );
192+ // Only clear saved bounds after successful restoration
193+ _savedBounds = null ;
194+ } catch (e) {
195+ // If restoration fails, keep saved bounds and try unmaximize
196+ commonPrint.log ('Failed to restore saved bounds: $e ' );
197+ await windowManager.unmaximize ();
198+ }
199+ } else {
200+ // Window was maximized externally (e.g., Win+Up, drag to edge)
201+ // Use system unmaximize, then verify the actual state
202+ await windowManager.unmaximize ();
203+ final actuallyMaximized = await windowManager.isMaximized ();
204+ if (actuallyMaximized) {
205+ // If still maximized, window might be in snap state
206+ // Restore to a default reasonable size
207+ try {
208+ final display = await screenRetriever.getPrimaryDisplay ();
209+ final visibleSize = display.visibleSize ?? display.size;
210+
211+ // Validate display size before using it
212+ if (visibleSize.width > 0 && visibleSize.height > 0 ) {
213+ await windowManager.setSize (
214+ Size (visibleSize.width * 0.8 , visibleSize.height * 0.8 ),
215+ );
216+ await windowManager.center ();
217+ } else {
218+ // Invalid display size, use hardcoded fallback
219+ commonPrint.log (
220+ 'Invalid display size, using fallback dimensions' ,
221+ );
222+ await windowManager.setSize (const Size (1280 , 720 ));
223+ await windowManager.center ();
224+ }
225+ } catch (e) {
226+ // Failed to get display info, use fallback size
227+ commonPrint.log ('Failed to get display info: $e ' );
228+ await windowManager.setSize (const Size (1280 , 720 ));
229+ await windowManager.center ();
230+ }
231+ }
232+ }
233+ _windowsBoundsMaximized = false ;
234+ isMaximizedNotifier.value = false ;
235+ } else {
236+ // Non-Windows platforms: use standard unmaximize
237+ await windowManager.unmaximize ();
238+ _windowsBoundsMaximized = false ;
239+ isMaximizedNotifier.value = false ;
240+ }
216241 } else {
217- await windowManager.maximize ();
218- isMaximizedNotifier.value = await windowManager.isMaximized ();
242+ // Maximize window
243+ if (system.isWindows) {
244+ // Save current window bounds
245+ final currentPosition = await windowManager.getPosition ();
246+ final currentSize = await windowManager.getSize ();
247+ _savedBounds = Rect .fromLTWH (
248+ currentPosition.dx,
249+ currentPosition.dy,
250+ currentSize.width,
251+ currentSize.height,
252+ );
253+
254+ // Determine which display the window is currently on by finding
255+ // the display that contains the window's center point
256+ final windowCenter = Offset (
257+ currentPosition.dx + currentSize.width / 2 ,
258+ currentPosition.dy + currentSize.height / 2 ,
259+ );
260+
261+ final displays = await screenRetriever.getAllDisplays ();
262+ Display ? targetDisplay;
263+
264+ for (final display in displays) {
265+ final displayBounds = Rect .fromLTWH (
266+ display.visiblePosition? .dx ?? 0 ,
267+ display.visiblePosition? .dy ?? 0 ,
268+ display.visibleSize? .width ?? display.size.width,
269+ display.visibleSize? .height ?? display.size.height,
270+ );
271+ if (displayBounds.contains (windowCenter)) {
272+ targetDisplay = display;
273+ break ;
274+ }
275+ }
276+
277+ // Fallback to primary display if window is not on any display
278+ targetDisplay ?? = await screenRetriever.getPrimaryDisplay ();
279+
280+ // Validate display information before using it
281+ final visiblePosition = targetDisplay.visiblePosition ?? Offset .zero;
282+ final visibleSize = targetDisplay.visibleSize ?? targetDisplay.size;
283+
284+ // Ensure we have valid dimensions
285+ if (visibleSize.width <= 0 || visibleSize.height <= 0 ) {
286+ // Display information is invalid, fallback to native maximize
287+ commonPrint.log (
288+ 'Invalid display dimensions, using native maximize' ,
289+ );
290+ await windowManager.maximize ();
291+ _windowsBoundsMaximized = false ;
292+ isMaximizedNotifier.value = await windowManager.isMaximized ();
293+ } else {
294+ await windowManager.setBounds (
295+ Rect .fromLTWH (
296+ visiblePosition.dx,
297+ visiblePosition.dy,
298+ visibleSize.width,
299+ visibleSize.height,
300+ ),
301+ );
302+ _windowsBoundsMaximized = true ;
303+ isMaximizedNotifier.value = true ;
304+ }
305+ } else {
306+ await windowManager.maximize ();
307+ isMaximizedNotifier.value = await windowManager.isMaximized ();
308+ }
219309 }
310+ } finally {
311+ _isUpdatingMaximized = false ;
220312 }
221313 }
222314
0 commit comments