From 72daad25f6fb57ee3db8c9d8136ecd622ceaf935 Mon Sep 17 00:00:00 2001 From: AdiAr11 Date: Mon, 15 Dec 2025 18:40:24 +1100 Subject: [PATCH 1/5] added window size configuration in settings UI with implementation --- lib/main.dart | 22 +- lib/providers/settings.dart | 12 + lib/settings/dialog.dart | 13 ++ lib/settings/sections/window_size.dart | 297 +++++++++++++++++++++++++ lib/widgets/close_dialog.dart | 19 +- 5 files changed, 351 insertions(+), 12 deletions(-) create mode 100644 lib/settings/sections/window_size.dart diff --git a/lib/main.dart b/lib/main.dart index 5516e7409..c6e8752a1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -36,9 +36,11 @@ import 'package:window_manager/window_manager.dart'; import 'package:rattle/app.dart'; import 'package:rattle/constants/temp_dir.dart'; import 'package:rattle/providers/pty.dart'; +import 'package:rattle/providers/settings.dart'; import 'package:rattle/utils/is_desktop.dart'; import 'package:rattle/utils/is_production.dart'; import 'package:rattle/utils/show_error.dart'; +import 'package:shared_preferences/shared_preferences.dart'; Future checkRInstallation() async { // Try to run the R command to check its availability. @@ -170,23 +172,21 @@ Future main() async { await windowManager.ensureInitialized(); - WindowOptions windowOptions = const WindowOptions( + // Load saved window size from SharedPreferences. + final prefs = await SharedPreferences.getInstance(); + final savedWidth = prefs.getDouble('windowWidth') ?? defaultWindowWidth; + final savedHeight = prefs.getDouble('windowHeight') ?? defaultWindowHeight; + + WindowOptions windowOptions = WindowOptions( // Setting [alwaysOnTop] here will ensure the desktop app starts on top of // other apps on the desktop so that it is visible. // // We later turn it off as we don't want to force it always on top. alwaysOnTop: true, - // We can override the size in the first instance by, for example in - // Linux, editing linux/my_application.cc. - // - // Setting it here has effect when Restarting the app while debugging. - - // However, since Windows has 1280x720 by default in the windows-specific - // windows/runner/main.cpp, line 29, it is best not to override it here - // since under Windows 950x600 is too small. - - // size: Size(950, 600), + // Use saved window size if available, otherwise use platform defaults + // The saved size is loaded from SharedPreferences + size: Size(savedWidth, savedHeight), // The [title] is used for the window manager's window title. title: 'Rattle - Data Science with R', diff --git a/lib/providers/settings.dart b/lib/providers/settings.dart index 0ea39dea5..10ca6e757 100644 --- a/lib/providers/settings.dart +++ b/lib/providers/settings.dart @@ -100,3 +100,15 @@ final stripCommentsProvider = StateProvider((ref) => false); final askOnExitProvider = StateProvider((ref) => true); final ignoreMissingTargetProvider = StateProvider((ref) => true); + +// Window size settings providers +// Default window size values (can be overridden by platform-specific defaults if needed) + +const double defaultWindowWidth = 1280.0; +const double defaultWindowHeight = 720.0; + +final windowWidthProvider = StateProvider((ref) => defaultWindowWidth); + +final windowHeightProvider = StateProvider((ref) => defaultWindowHeight); + +final rememberWindowSizeProvider = StateProvider((ref) => true); diff --git a/lib/settings/dialog.dart b/lib/settings/dialog.dart index d407e07bc..589628207 100644 --- a/lib/settings/dialog.dart +++ b/lib/settings/dialog.dart @@ -42,6 +42,7 @@ import 'package:rattle/settings/sections/dataset_toggles.dart'; import 'package:rattle/settings/sections/graphic_theme.dart'; import 'package:rattle/settings/sections/script.dart'; import 'package:rattle/settings/sections/session.dart'; +import 'package:rattle/settings/sections/window_size.dart'; import 'package:rattle/settings/utils/handle_cancel_button.dart'; class SettingsDialog extends ConsumerStatefulWidget { @@ -117,6 +118,17 @@ class SettingsDialogState extends ConsumerState { ref.read(ignoreMissingTargetProvider.notifier).state = prefs.getBool('ignoreMissingTarget') ?? true; + + // Load window size settings from shared preferences + + ref.read(windowWidthProvider.notifier).state = + prefs.getDouble('windowWidth') ?? defaultWindowWidth; + + ref.read(windowHeightProvider.notifier).state = + prefs.getDouble('windowHeight') ?? defaultWindowHeight; + + ref.read(rememberWindowSizeProvider.notifier).state = + prefs.getBool('rememberWindowSize') ?? true; } /// Load all numeric settings from shared preferences. @@ -190,6 +202,7 @@ class SettingsDialogState extends ConsumerState { DatasetToggles(), GraphicTheme(), Session(), + const WindowSize(), Script(), ], ), diff --git a/lib/settings/sections/window_size.dart b/lib/settings/sections/window_size.dart new file mode 100644 index 000000000..275616479 --- /dev/null +++ b/lib/settings/sections/window_size.dart @@ -0,0 +1,297 @@ +/// Window size section. +// +// Time-stamp: "Sunday 2025-12-14 17:21:00 +1100 Graham Williams" +// +/// Copyright (C) 2024, Togaware Pty Ltd +/// +/// Licensed under the GNU General Public License, Version 3 (the "License"); +/// +/// License: https://opensource.org/license/gpl-3-0 +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . +/// +/// Authors: Aditya Arora + +library; + +import 'package:flutter/material.dart'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:markdown_tooltip/markdown_tooltip.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:window_manager/window_manager.dart'; + +import 'package:rattle/constants/spacing.dart'; +import 'package:rattle/providers/settings.dart'; +import 'package:rattle/utils/is_desktop.dart'; + +class WindowSize extends ConsumerStatefulWidget { + const WindowSize({super.key}); + + @override + ConsumerState createState() => _WindowSizeState(); +} + +class _WindowSizeState extends ConsumerState { + late final TextEditingController _widthController; + late final TextEditingController _heightController; + double? _currentWidth; + double? _currentHeight; + + @override + void initState() { + super.initState(); + _widthController = TextEditingController(); + _heightController = TextEditingController(); + _loadCurrentWindowSize(); + _loadSettings(); + } + + @override + void dispose() { + _widthController.dispose(); + _heightController.dispose(); + super.dispose(); + } + + /// Load the current window size from the window manager + Future _loadCurrentWindowSize() async { + if (isDesktop) { + try { + final size = await windowManager.getSize(); + setState(() { + _currentWidth = size.width; + _currentHeight = size.height; + }); + } catch (e) { + // Window manager might not be available + debugPrint('Error loading current window size: $e'); + } + } + } + + /// Load settings from providers and update text controllers + void _loadSettings() { + final savedWidth = ref.read(windowWidthProvider); + final savedHeight = ref.read(windowHeightProvider); + + _widthController.text = savedWidth.toStringAsFixed(0); + _heightController.text = savedHeight.toStringAsFixed(0); + } + + /// Save window size settings to shared preferences. + Future _saveWindowSizeSettings() async { + final prefs = await SharedPreferences.getInstance(); + + final width = double.tryParse(_widthController.text); + final height = double.tryParse(_heightController.text); + + if (width != null && width > 0) { + ref.read(windowWidthProvider.notifier).state = width; + await prefs.setDouble('windowWidth', width); + } + + if (height != null && height > 0) { + ref.read(windowHeightProvider.notifier).state = height; + await prefs.setDouble('windowHeight', height); + } + + // Save remember window size setting. + final rememberSize = ref.read(rememberWindowSizeProvider); + await prefs.setBool('rememberWindowSize', rememberSize); + } + + /// Apply the window size from the text fields to the actual window. + Future _applyWindowSize() async { + + final width = double.tryParse(_widthController.text); + final height = double.tryParse(_heightController.text); + + if (width != null && width > 0 && height != null && height > 0) { + try { + await windowManager.setSize(Size(width, height)); + await _loadCurrentWindowSize(); + await _saveWindowSizeSettings(); + + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Window size applied and saved'), + duration: Duration(seconds: 2), + ), + ); + } + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Error applying window size: $e'), + duration: const Duration(seconds: 3), + ), + ); + } + } + } + } + + /// Reset window size settings to defaults. + void _resetWindowSize() { + ref.read(windowWidthProvider.notifier).state = defaultWindowWidth; + ref.read(windowHeightProvider.notifier).state = defaultWindowHeight; + ref.read(rememberWindowSizeProvider.notifier).state = true; + + _widthController.text = defaultWindowWidth.toStringAsFixed(0); + _heightController.text = defaultWindowHeight.toStringAsFixed(0); + + _saveWindowSizeSettings(); + } + + @override + Widget build(BuildContext context) { + + final rememberSize = ref.watch(rememberWindowSizeProvider); + final savedWidth = ref.watch(windowWidthProvider); + final savedHeight = ref.watch(windowHeightProvider); + + // Keep controllers in sync with providers. + if (_widthController.text != savedWidth.toStringAsFixed(0)) { + _widthController.text = savedWidth.toStringAsFixed(0); + } + if (_heightController.text != savedHeight.toStringAsFixed(0)) { + _heightController.text = savedHeight.toStringAsFixed(0); + } + + return Column( + children: [ + Row( + children: [ + const Text( + 'Window Size', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + configRowGap, + MarkdownTooltip( + message: ''' + + **Reset Window Size:** Tap here to reset the window size + settings to the default values (${defaultWindowWidth.toInt()}x${defaultWindowHeight.toInt()}). + + ''', + child: ElevatedButton( + onPressed: _resetWindowSize, + child: const Text('Reset'), + ), + ), + ], + ), + configRowGap, + // Display current window size. + if (_currentWidth != null && _currentHeight != null) + Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: Text( + 'Current window size: ${_currentWidth!.toInt()} × ${_currentHeight!.toInt()}', + style: const TextStyle(fontSize: 14, fontStyle: FontStyle.italic), + ), + ), + configRowGap, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + MarkdownTooltip( + message: ''' + + **Window Width:** Set the desired window width in pixels. + This value will be used when the app starts up. + + ''', + child: SizedBox( + width: 150, + child: TextField( + controller: _widthController, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Width (pixels)', + border: OutlineInputBorder(), + ), + ), + ), + ), + configRowGap, + MarkdownTooltip( + message: ''' + + **Window Height:** Set the desired window height in pixels. + This value will be used when the app starts up. + + ''', + child: SizedBox( + width: 150, + child: TextField( + controller: _heightController, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Height (pixels)', + border: OutlineInputBorder(), + ), + ), + ), + ), + configRowGap, + ElevatedButton( + onPressed: _applyWindowSize, + child: const Text('Apply'), + ), + ], + ), + configRowGap, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + MarkdownTooltip( + message: ''' + + **Remember Window Size on Exit:** When enabled, the current + window size will be automatically saved when you exit the app, + overriding any manually set values. When disabled, the window + size will only use the manually set values and will not be + updated on exit. + + ''', + child: Row( + children: [ + const Text( + 'Remember window size on exit', + style: TextStyle(fontSize: 16), + ), + configRowGap, + Switch( + value: rememberSize, + onChanged: (value) { + ref.read(rememberWindowSizeProvider.notifier).state = value; + _saveWindowSizeSettings(); + }, + ), + ], + ), + ), + ], + ), + settingsGroupGap, + const Divider(), + ], + ); + } +} + diff --git a/lib/widgets/close_dialog.dart b/lib/widgets/close_dialog.dart index febcac86a..a4908929b 100644 --- a/lib/widgets/close_dialog.dart +++ b/lib/widgets/close_dialog.dart @@ -120,7 +120,24 @@ class _CloseDialogState extends ConsumerState { ); } - void _closeApp() { + void _closeApp() async { + // save window size before closing if the setting is enabled + final rememberSize = ref.read(rememberWindowSizeProvider); + if (rememberSize) { + try { + final size = await WindowManager.instance.getSize(); + final prefs = await SharedPreferences.getInstance(); + await prefs.setDouble('windowWidth', size.width); + await prefs.setDouble('windowHeight', size.height); + + // update providers to reflect saved values + ref.read(windowWidthProvider.notifier).state = size.width; + ref.read(windowHeightProvider.notifier).state = size.height; + } catch (e) { + debugPrint('Error saving window size: $e'); + } + } + Navigator.of(context).pop(); cleanUpTempDirs(); WindowManager.instance.setPreventClose(false); From 434ddf2f8b37d6aa4b7d6ab8c98fee5b1ed4075d Mon Sep 17 00:00:00 2001 From: AdiAr11 Date: Mon, 15 Dec 2025 18:54:27 +1100 Subject: [PATCH 2/5] reset button fix and window size text alignment fix --- lib/settings/sections/window_size.dart | 27 +++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/settings/sections/window_size.dart b/lib/settings/sections/window_size.dart index 275616479..c632eac4e 100644 --- a/lib/settings/sections/window_size.dart +++ b/lib/settings/sections/window_size.dart @@ -75,7 +75,6 @@ class _WindowSizeState extends ConsumerState { _currentHeight = size.height; }); } catch (e) { - // Window manager might not be available debugPrint('Error loading current window size: $e'); } } @@ -90,7 +89,7 @@ class _WindowSizeState extends ConsumerState { _heightController.text = savedHeight.toStringAsFixed(0); } - /// Save window size settings to shared preferences. + /// Save window size settings to shared preferences Future _saveWindowSizeSettings() async { final prefs = await SharedPreferences.getInstance(); @@ -107,12 +106,12 @@ class _WindowSizeState extends ConsumerState { await prefs.setDouble('windowHeight', height); } - // Save remember window size setting. + // Save remember window size setting final rememberSize = ref.read(rememberWindowSizeProvider); await prefs.setBool('rememberWindowSize', rememberSize); } - /// Apply the window size from the text fields to the actual window. + /// Apply the window size from the text fields to the actual window Future _applyWindowSize() async { final width = double.tryParse(_widthController.text); @@ -145,8 +144,8 @@ class _WindowSizeState extends ConsumerState { } } - /// Reset window size settings to defaults. - void _resetWindowSize() { + /// Reset window size settings to defaults + Future _resetWindowSize() async { ref.read(windowWidthProvider.notifier).state = defaultWindowWidth; ref.read(windowHeightProvider.notifier).state = defaultWindowHeight; ref.read(rememberWindowSizeProvider.notifier).state = true; @@ -154,6 +153,8 @@ class _WindowSizeState extends ConsumerState { _widthController.text = defaultWindowWidth.toStringAsFixed(0); _heightController.text = defaultWindowHeight.toStringAsFixed(0); + await windowManager.setSize(Size(defaultWindowWidth, defaultWindowHeight)); + _saveWindowSizeSettings(); } @@ -164,7 +165,7 @@ class _WindowSizeState extends ConsumerState { final savedWidth = ref.watch(windowWidthProvider); final savedHeight = ref.watch(windowHeightProvider); - // Keep controllers in sync with providers. + // Keep controllers in sync with providers if (_widthController.text != savedWidth.toStringAsFixed(0)) { _widthController.text = savedWidth.toStringAsFixed(0); } @@ -173,6 +174,7 @@ class _WindowSizeState extends ConsumerState { } return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ @@ -196,14 +198,11 @@ class _WindowSizeState extends ConsumerState { ], ), configRowGap, - // Display current window size. + // Display current window size if (_currentWidth != null && _currentHeight != null) - Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Text( - 'Current window size: ${_currentWidth!.toInt()} × ${_currentHeight!.toInt()}', - style: const TextStyle(fontSize: 14, fontStyle: FontStyle.italic), - ), + Text( + 'Current window size: ${_currentWidth!.toInt()} × ${_currentHeight!.toInt()}', + style: const TextStyle(fontSize: 16,), ), configRowGap, Row( From 1ce2e61aa82afc89044f6ac1e9f27405fd0b72ab Mon Sep 17 00:00:00 2001 From: AdiAr11 Date: Mon, 15 Dec 2025 19:08:49 +1100 Subject: [PATCH 3/5] fixed current window size text not changing and reflecting correct values. removed changed size snackbar as it was not visible anyways --- lib/settings/sections/window_size.dart | 28 +++++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/settings/sections/window_size.dart b/lib/settings/sections/window_size.dart index c632eac4e..8ef85847a 100644 --- a/lib/settings/sections/window_size.dart +++ b/lib/settings/sections/window_size.dart @@ -43,7 +43,7 @@ class WindowSize extends ConsumerStatefulWidget { ConsumerState createState() => _WindowSizeState(); } -class _WindowSizeState extends ConsumerState { +class _WindowSizeState extends ConsumerState with WindowListener { late final TextEditingController _widthController; late final TextEditingController _heightController; double? _currentWidth; @@ -54,12 +54,14 @@ class _WindowSizeState extends ConsumerState { super.initState(); _widthController = TextEditingController(); _heightController = TextEditingController(); + windowManager.addListener(this); _loadCurrentWindowSize(); _loadSettings(); } @override void dispose() { + windowManager.removeListener(this); _widthController.dispose(); _heightController.dispose(); super.dispose(); @@ -122,15 +124,7 @@ class _WindowSizeState extends ConsumerState { await windowManager.setSize(Size(width, height)); await _loadCurrentWindowSize(); await _saveWindowSizeSettings(); - - if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Window size applied and saved'), - duration: Duration(seconds: 2), - ), - ); - } + } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( @@ -158,6 +152,20 @@ class _WindowSizeState extends ConsumerState { _saveWindowSizeSettings(); } + @override + void onWindowResize() async { + if (!mounted) return; + try { + final size = await windowManager.getSize(); + setState(() { + _currentWidth = size.width; + _currentHeight = size.height; + }); + } catch (e) { + debugPrint('Error updating window size on resize: $e'); + } + } + @override Widget build(BuildContext context) { From c668de7d5f6c8d1837290040a3aefd35427413c5 Mon Sep 17 00:00:00 2001 From: AdiAr11 Date: Sat, 3 Jan 2026 23:58:50 +1100 Subject: [PATCH 4/5] fixing lint issues --- lib/providers/settings.dart | 3 ++- lib/settings/sections/window_size.dart | 11 +++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/providers/settings.dart b/lib/providers/settings.dart index 10ca6e757..bcb35ecaf 100644 --- a/lib/providers/settings.dart +++ b/lib/providers/settings.dart @@ -109,6 +109,7 @@ const double defaultWindowHeight = 720.0; final windowWidthProvider = StateProvider((ref) => defaultWindowWidth); -final windowHeightProvider = StateProvider((ref) => defaultWindowHeight); +final windowHeightProvider = + StateProvider((ref) => defaultWindowHeight); final rememberWindowSizeProvider = StateProvider((ref) => true); diff --git a/lib/settings/sections/window_size.dart b/lib/settings/sections/window_size.dart index 8ef85847a..6fa84b5b7 100644 --- a/lib/settings/sections/window_size.dart +++ b/lib/settings/sections/window_size.dart @@ -115,7 +115,6 @@ class _WindowSizeState extends ConsumerState with WindowListener { /// Apply the window size from the text fields to the actual window Future _applyWindowSize() async { - final width = double.tryParse(_widthController.text); final height = double.tryParse(_heightController.text); @@ -124,7 +123,6 @@ class _WindowSizeState extends ConsumerState with WindowListener { await windowManager.setSize(Size(width, height)); await _loadCurrentWindowSize(); await _saveWindowSizeSettings(); - } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( @@ -168,7 +166,6 @@ class _WindowSizeState extends ConsumerState with WindowListener { @override Widget build(BuildContext context) { - final rememberSize = ref.watch(rememberWindowSizeProvider); final savedWidth = ref.watch(windowWidthProvider); final savedHeight = ref.watch(windowHeightProvider); @@ -210,7 +207,9 @@ class _WindowSizeState extends ConsumerState with WindowListener { if (_currentWidth != null && _currentHeight != null) Text( 'Current window size: ${_currentWidth!.toInt()} × ${_currentHeight!.toInt()}', - style: const TextStyle(fontSize: 16,), + style: const TextStyle( + fontSize: 16, + ), ), configRowGap, Row( @@ -286,7 +285,8 @@ class _WindowSizeState extends ConsumerState with WindowListener { Switch( value: rememberSize, onChanged: (value) { - ref.read(rememberWindowSizeProvider.notifier).state = value; + ref.read(rememberWindowSizeProvider.notifier).state = + value; _saveWindowSizeSettings(); }, ), @@ -301,4 +301,3 @@ class _WindowSizeState extends ConsumerState with WindowListener { ); } } - From 386a3e3a912b2d82fbfb83e12ce402a5e93e9977 Mon Sep 17 00:00:00 2001 From: AdiAr11 Date: Sun, 4 Jan 2026 00:04:42 +1100 Subject: [PATCH 5/5] fixed const lint issue and import alphabetical order in main.dar --- lib/main.dart | 2 +- lib/settings/dialog.dart | 2 +- lib/settings/sections/window_size.dart | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index c6e8752a1..156a8c5b8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -31,6 +31,7 @@ import 'package:flutter/material.dart'; import 'package:catppuccin_flutter/catppuccin_flutter.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:window_manager/window_manager.dart'; import 'package:rattle/app.dart'; @@ -40,7 +41,6 @@ import 'package:rattle/providers/settings.dart'; import 'package:rattle/utils/is_desktop.dart'; import 'package:rattle/utils/is_production.dart'; import 'package:rattle/utils/show_error.dart'; -import 'package:shared_preferences/shared_preferences.dart'; Future checkRInstallation() async { // Try to run the R command to check its availability. diff --git a/lib/settings/dialog.dart b/lib/settings/dialog.dart index 589628207..144acd5dd 100644 --- a/lib/settings/dialog.dart +++ b/lib/settings/dialog.dart @@ -202,7 +202,7 @@ class SettingsDialogState extends ConsumerState { DatasetToggles(), GraphicTheme(), Session(), - const WindowSize(), + WindowSize(), Script(), ], ), diff --git a/lib/settings/sections/window_size.dart b/lib/settings/sections/window_size.dart index 6fa84b5b7..2b20bb22d 100644 --- a/lib/settings/sections/window_size.dart +++ b/lib/settings/sections/window_size.dart @@ -145,7 +145,8 @@ class _WindowSizeState extends ConsumerState with WindowListener { _widthController.text = defaultWindowWidth.toStringAsFixed(0); _heightController.text = defaultWindowHeight.toStringAsFixed(0); - await windowManager.setSize(Size(defaultWindowWidth, defaultWindowHeight)); + await windowManager + .setSize(const Size(defaultWindowWidth, defaultWindowHeight)); _saveWindowSizeSettings(); }