From 06f0636c83b274c1323cf0a10fae62c9d9e98abb Mon Sep 17 00:00:00 2001 From: hawkeye Date: Thu, 5 Sep 2024 22:58:59 -0400 Subject: [PATCH 1/7] Update dynamic LOD --- MainApp/AppWindow/AppMainWindow.xaml.cs | 6 ++ Orchestration/DynamicLodOrchestrator.cs | 96 +++++++++--------------- Orchestration/FlightSimOrchestrator.cs | 20 ++--- Orchestration/PanelPopOutOrchestrator.cs | 3 + SimconnectAgent/FpsCalc.cs | 34 ++++++--- 5 files changed, 80 insertions(+), 79 deletions(-) diff --git a/MainApp/AppWindow/AppMainWindow.xaml.cs b/MainApp/AppWindow/AppMainWindow.xaml.cs index d916059..64860a3 100644 --- a/MainApp/AppWindow/AppMainWindow.xaml.cs +++ b/MainApp/AppWindow/AppMainWindow.xaml.cs @@ -26,6 +26,12 @@ namespace MSFSPopoutPanelManager.MainApp.AppWindow StateChanged += AppWindow_StateChanged; WindowActionManager.OnPopOutManagerAlwaysOnTopChanged += (_, e) => { Topmost = e; }; MouseLeftButtonDown += (_, _) => DragMove(); + + GotFocus += (_, _) => + { + if (_viewModel.AppSettingData.ApplicationSetting.GeneralSetting.AlwaysOnTop) + WindowActionManager.ApplyAlwaysOnTop(_viewModel.ApplicationHandle, PanelType.PopOutManager, true); + }; } private void AppWindow_Loaded(object sender, RoutedEventArgs e) diff --git a/Orchestration/DynamicLodOrchestrator.cs b/Orchestration/DynamicLodOrchestrator.cs index ff0c937..0d7a02f 100644 --- a/Orchestration/DynamicLodOrchestrator.cs +++ b/Orchestration/DynamicLodOrchestrator.cs @@ -1,7 +1,6 @@ using MSFSPopoutPanelManager.DomainModel.DynamicLod; using MSFSPopoutPanelManager.DomainModel.Setting; using MSFSPopoutPanelManager.Shared; -using MSFSPopoutPanelManager.SimConnectAgent; using MSFSPopoutPanelManager.WindowsAgent; using System; using System.Diagnostics; @@ -17,12 +16,9 @@ namespace MSFSPopoutPanelManager.Orchestration private const int PROCESS_VM_WRITE = 0x0020; private const long OFFSET_MODULE_BASE =0x004B2368; private const long OFFSET_POINTER_MAIN = 0x3D0; - private const long OFFSET_POINTER_TLOD_VR = 0x114; private const long OFFSET_POINTER_TLOD = 0xC; private const long OFFSET_POINTER_OLOD = 0xC; - private const long OFFSET_POINTER_CLOUDQ = 0x44; - private const long OFFSET_POINTER_CLOUDQ_VR = 0x108; - private const long OFFSET_POINTER_VR_MODE = 0x1C; + private const long OFFSET_POINTER_CLOUD_QUALITY = 0x44; private const long OFFSET_POINTER_FG_MODE = 0x4A; private const long OFFSET_POINTER_ANSIO_FILTER = -0x18; private const long OFFSET_POINTER_WATER_WAVES = 0x3C; @@ -34,19 +30,15 @@ namespace MSFSPopoutPanelManager.Orchestration private long _addressTlod; private long _addressOlod; - private long _addressTlodVr; - private long _addressOlodVr; private long _addressCloudQ; - private long _addressCloudQVr; - private long _addressVrMode; private long _addressFgMode; private DynamicLodSetting DynamicLodSetting => AppSettingData.ApplicationSetting.DynamicLodSetting; - private DynamicLodSimData SimData => FlightSimData.DynamicLodSimData; + private DynamicLodSimData DynamicLodSimData => FlightSimData.DynamicLodSimData; private DateTime _lastLodUpdateTime = DateTime.Now; - private bool _isDecreasedCloudQualityActive = false; + private bool _isDecreasedCloudQualityActive; public DynamicLodOrchestrator(SharedStorage sharedStorage) : base(sharedStorage) {} @@ -70,13 +62,9 @@ namespace MSFSPopoutPanelManager.Orchestration if (_addressTlod > 0) { - _addressTlodVr = ReadMemory(_addressTlod) + OFFSET_POINTER_TLOD_VR; _addressTlod = ReadMemory(_addressTlod) + OFFSET_POINTER_TLOD; _addressOlod = _addressTlod + OFFSET_POINTER_OLOD; - _addressOlodVr = _addressTlodVr + OFFSET_POINTER_OLOD; - _addressCloudQ = _addressTlod + OFFSET_POINTER_CLOUDQ; - _addressCloudQVr = _addressCloudQ + OFFSET_POINTER_CLOUDQ_VR; - _addressVrMode = _addressTlod - OFFSET_POINTER_VR_MODE; + _addressCloudQ = _addressTlod + OFFSET_POINTER_CLOUD_QUALITY; _addressFgMode = _addressTlod - OFFSET_POINTER_FG_MODE; if (!MemoryBoundaryTest()) @@ -99,9 +87,8 @@ namespace MSFSPopoutPanelManager.Orchestration if (DynamicLodSetting.ResetEnabled) { - var isVr = ReadIsVr(); - WriteMemory(isVr ? _addressTlodVr : _addressTlod, DynamicLodSetting.ResetTlod / 100.0f); - WriteMemory(isVr ? _addressOlodVr : _addressOlod, DynamicLodSetting.ResetOlod / 100.0f); + WriteMemory(_addressTlod, DynamicLodSetting.ResetTlod / 100.0f); + WriteMemory(_addressOlod, DynamicLodSetting.ResetOlod / 100.0f); } _isActive = false; @@ -109,19 +96,19 @@ namespace MSFSPopoutPanelManager.Orchestration Debug.WriteLine($"Reset to custom LOD: TLOD: {DynamicLodSetting.ResetTlod}, OLOD: {DynamicLodSetting.ResetOlod}"); } - public int ReadTlod(bool isVr = false) + public int ReadTlod() { - return Convert.ToInt32(ReadMemory(isVr ? _addressTlodVr : _addressTlod) * 100.0f); + return Convert.ToInt32(ReadMemory(_addressTlod) * 100.0f); } - public int ReadOlod(bool isVr = false) + public int ReadOlod() { - return Convert.ToInt32(ReadMemory(isVr ? _addressOlodVr : _addressOlod) * 100.0f); + return Convert.ToInt32(ReadMemory(_addressOlod) * 100.0f); } - public string ReadCloudQuality(bool isVr = false) + public string ReadCloudQuality() { - return ReadCloudQualitySimValue(isVr) switch + return ReadCloudQualitySimValue() switch { 0 => "Low", 1 => "Medium", @@ -131,33 +118,25 @@ namespace MSFSPopoutPanelManager.Orchestration }; } - public int ReadCloudQualitySimValue(bool isVr = false) + public int ReadCloudQualitySimValue() { - return Convert.ToInt32(ReadMemory(isVr ? _addressCloudQVr : _addressCloudQ)); + return Convert.ToInt32(ReadMemory(_addressCloudQ)); } - public bool ReadIsVr() + public bool ReadIsFg() { - return ReadMemory(_addressVrMode) == 1; - } - - public bool ReadIsFg(bool isVr) - { - if (isVr) - return false; - return ReadMemory(_addressFgMode) == 1; } - public void UpdateLod(bool isVr) + public void UpdateLod() { + if (!FlightSimData.IsFlightStarted || !FlightSimData.IsInCockpit) + return; + if (DateTime.Now - _lastLodUpdateTime <= TimeSpan.FromSeconds(1)) return; - if (!FlightSimData.IsFlightStarted || !FlightSimData.IsInCockpit || (DynamicLodSetting.PauseOutsideCockpitView && FlightSimData.CameraState != CameraState.Cockpit)) - return; - - var deltaFps = SimData.Fps - DynamicLodSetting.TargetedFps; + var deltaFps = DynamicLodSimData.Fps - DynamicLodSetting.TargetedFps; if (Math.Abs(deltaFps) < DynamicLodSetting.TargetedFps * DynamicLodSetting.FpsTolerance / 100.0) // within FPS tolerance return; @@ -246,10 +225,9 @@ namespace MSFSPopoutPanelManager.Orchestration private bool MemoryBoundaryTest() { // Boundary check a few known setting memory addresses to see if any fail which likely indicates MSFS memory map has changed - if (ReadTlod() < 10 || ReadTlod() > 1000 || ReadTlod(true) < 10 || ReadTlod(true) > 1000 - || ReadOlod() < 10 || ReadOlod() > 1000 || ReadOlod(true) < 10 || ReadOlod(true) > 1000 - || ReadCloudQuality() == "N/A" || ReadCloudQuality(true) == "N/A" - || ReadMemory(_addressVrMode) < 0 || ReadMemory(_addressVrMode) > 1 + if (ReadTlod() < 10 || ReadTlod() > 1000 || ReadTlod() < 10 || ReadTlod() > 1000 + || ReadOlod() < 10 || ReadOlod() > 1000 || ReadOlod() < 10 || ReadOlod() > 1000 + || ReadCloudQuality() == "N/A" || ReadCloudQuality() == "N/A" || ReadMemory(_addressTlod + OFFSET_POINTER_ANSIO_FILTER) < 1 || ReadMemory(_addressTlod + OFFSET_POINTER_ANSIO_FILTER) > 16 || !(ReadMemory(_addressTlod + OFFSET_POINTER_WATER_WAVES) == 128 || ReadMemory(_addressTlod + OFFSET_POINTER_WATER_WAVES) == 256 || ReadMemory(_addressTlod + OFFSET_POINTER_WATER_WAVES) == 512)) { @@ -259,12 +237,12 @@ namespace MSFSPopoutPanelManager.Orchestration return true; } - private void SetTlod(int deltaFps, bool isVr = false) + private void SetTlod(int deltaFps) { var tlodStep = Math.Max(5, Math.Abs(deltaFps / 2)); - var newTlod = SimData.Tlod + Math.Sign(deltaFps) * tlodStep; + var newTlod = DynamicLodSimData.Tlod + Math.Sign(deltaFps) * tlodStep; - if (DynamicLodSetting.TlodMinOnGround && SimData.AltAboveGround <= DynamicLodSetting.AltTlodBase) + if (DynamicLodSetting.TlodMinOnGround && DynamicLodSimData.AltAboveGround <= DynamicLodSetting.AltTlodBase) { newTlod = DynamicLodSetting.TlodMin; } @@ -277,17 +255,17 @@ namespace MSFSPopoutPanelManager.Orchestration newTlod = DynamicLodSetting.TlodMax; } - if (ReadTlod(isVr) == newTlod) + if (ReadTlod() == newTlod) return; // Adjust cloud quality if applicable - if (DynamicLodSetting.DecreaseCloudQuality && (!DynamicLodSetting.TlodMinOnGround && !(SimData.AltAboveGround <= DynamicLodSetting.AltTlodBase))) + if (DynamicLodSetting.DecreaseCloudQuality && (!DynamicLodSetting.TlodMinOnGround && !(DynamicLodSimData.AltAboveGround <= DynamicLodSetting.AltTlodBase))) { switch (deltaFps) { case < 0 when newTlod < DynamicLodSetting.CloudRecoveryTlod && !_isDecreasedCloudQualityActive: _isDecreasedCloudQualityActive = true; - WriteMemory(isVr ? _addressCloudQVr : _addressCloudQ, ReadCloudQualitySimValue(isVr) - 1); + WriteMemory(_addressCloudQ, ReadCloudQualitySimValue() - 1); _lastLodUpdateTime = _lastLodUpdateTime.AddSeconds(2); // Add extra delay for cloud setting to take effect @@ -296,7 +274,7 @@ namespace MSFSPopoutPanelManager.Orchestration return; case > 0 when newTlod >= DynamicLodSetting.CloudRecoveryTlod && _isDecreasedCloudQualityActive: _isDecreasedCloudQualityActive = false; - WriteMemory(isVr ? _addressCloudQVr : _addressCloudQ, ReadCloudQualitySimValue(isVr) + 1); + WriteMemory(_addressCloudQ, ReadCloudQualitySimValue() + 1); _lastLodUpdateTime = _lastLodUpdateTime.AddSeconds(2); Debug.WriteLine("New Cloud Quality written - 3."); @@ -306,31 +284,31 @@ namespace MSFSPopoutPanelManager.Orchestration } Debug.WriteLine($"New TLOD written - {newTlod}."); - WriteMemory(isVr ? _addressTlodVr : _addressTlod, newTlod / 100.0f); + WriteMemory(_addressTlod, newTlod / 100.0f); } - private void SetOlod(bool isVr = false) + private void SetOlod() { int newOlod; - if (SimData.AltAboveGround < DynamicLodSetting.AltOlodBase) + if (DynamicLodSimData.AltAboveGround < DynamicLodSetting.AltOlodBase) { newOlod = DynamicLodSetting.OlodBase; } - else if (SimData.AltAboveGround > DynamicLodSetting.AltOlodTop) + else if (DynamicLodSimData.AltAboveGround > DynamicLodSetting.AltOlodTop) { newOlod = DynamicLodSetting.OlodTop; } else { - newOlod = Convert.ToInt32(DynamicLodSetting.OlodBase - (DynamicLodSetting.OlodBase - DynamicLodSetting.OlodTop) * (SimData.AltAboveGround - DynamicLodSetting.AltOlodBase) / (DynamicLodSetting.AltOlodTop - DynamicLodSetting.AltOlodBase)); + newOlod = Convert.ToInt32(DynamicLodSetting.OlodBase - (DynamicLodSetting.OlodBase - DynamicLodSetting.OlodTop) * (DynamicLodSimData.AltAboveGround - DynamicLodSetting.AltOlodBase) / (DynamicLodSetting.AltOlodTop - DynamicLodSetting.AltOlodBase)); } - if (ReadOlod(isVr) == newOlod) + if (ReadOlod() == newOlod) return; Debug.WriteLine($"New OLOD written - {newOlod}."); - WriteMemory(isVr ? _addressOlodVr : _addressOlod, newOlod / 100.0f); + WriteMemory(_addressOlod, newOlod / 100.0f); } } } diff --git a/Orchestration/FlightSimOrchestrator.cs b/Orchestration/FlightSimOrchestrator.cs index b195575..d80a2c4 100644 --- a/Orchestration/FlightSimOrchestrator.cs +++ b/Orchestration/FlightSimOrchestrator.cs @@ -15,7 +15,7 @@ namespace MSFSPopoutPanelManager.Orchestration private System.Timers.Timer _msfsGameExitDetectionTimer; private SimConnectProvider _simConnectProvider; - private DynamicLodOrchestrator _dynamicLodOrchestrator; + private readonly DynamicLodOrchestrator _dynamicLodOrchestrator; private bool _isTurnedOnPower; private bool _isTurnedOnAvionics; @@ -77,17 +77,14 @@ namespace MSFSPopoutPanelManager.Orchestration if (!AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled || !FlightSimData.IsFlightStarted) return; - var isVr = _dynamicLodOrchestrator.ReadIsVr(); - MapDynamicLodSimConnectData(e, isVr); - var isPaused = (AppSettingData.ApplicationSetting.DynamicLodSetting.PauseWhenMsfsLoseFocus && !WindowActionManager.IsMsfsInFocus()) || (AppSettingData.ApplicationSetting.DynamicLodSetting.PauseOutsideCockpitView && FlightSimData.CameraState != CameraState.Cockpit); if (isPaused) return; - FlightSimData.DynamicLodSimData.Fps = FpsCalc.GetAverageFps(_dynamicLodOrchestrator.ReadIsFg(isVr) ? _currentFps * 2 : _currentFps); - _dynamicLodOrchestrator.UpdateLod(isVr); + MapDynamicLodSimConnectData(e); + _dynamicLodOrchestrator.UpdateLod(); }; _simConnectProvider.OnSimConnectDataEventFrameRefreshed += (_, e) => @@ -393,6 +390,7 @@ namespace MSFSPopoutPanelManager.Orchestration FlightSimData.IsFlightStarted = false; StopDynamicLod(); + FpsCalc.Reset(); FlightSimData.DynamicLodSimData.Clear(); } @@ -492,7 +490,7 @@ namespace MSFSPopoutPanelManager.Orchestration FlightSimData.HudBarData.SimRate = newValue; } - private void MapDynamicLodSimConnectData(List simData, bool isVr) + private void MapDynamicLodSimConnectData(List simData) { if (CompareSimConnectData(simData, SimDataDefinitions.PropName.PlaneAltAboveGround, FlightSimData.DynamicLodSimData.Agl, out var newValue)) FlightSimData.DynamicLodSimData.Agl = newValue; @@ -509,17 +507,19 @@ namespace MSFSPopoutPanelManager.Orchestration if (CompareSimConnectData(simData, SimDataDefinitions.PropName.SimOnGround, 1.0f, out newValue)) FlightSimData.DynamicLodSimData.PlaneOnGround = Convert.ToBoolean(newValue); - var tlod = _dynamicLodOrchestrator.ReadTlod(isVr); + var tlod = _dynamicLodOrchestrator.ReadTlod(); if (FlightSimData.DynamicLodSimData.Tlod != tlod) FlightSimData.DynamicLodSimData.Tlod = tlod; - var olod = _dynamicLodOrchestrator.ReadOlod(isVr); + var olod = _dynamicLodOrchestrator.ReadOlod(); if (FlightSimData.DynamicLodSimData.Olod != olod) FlightSimData.DynamicLodSimData.Olod = olod; - var cloudQuality = _dynamicLodOrchestrator.ReadCloudQuality(isVr); + var cloudQuality = _dynamicLodOrchestrator.ReadCloudQuality(); if (FlightSimData.DynamicLodSimData.CloudQuality != cloudQuality) FlightSimData.DynamicLodSimData.CloudQuality = cloudQuality; + + FlightSimData.DynamicLodSimData.Fps = FpsCalc.GetAverageFps(_dynamicLodOrchestrator.ReadIsFg() ? _currentFps * 2 : _currentFps); } private int _currentFps; diff --git a/Orchestration/PanelPopOutOrchestrator.cs b/Orchestration/PanelPopOutOrchestrator.cs index 2dfc340..744fbfc 100644 --- a/Orchestration/PanelPopOutOrchestrator.cs +++ b/Orchestration/PanelPopOutOrchestrator.cs @@ -419,6 +419,9 @@ namespace MSFSPopoutPanelManager.Orchestration WindowActionManager.SetWindowTitleBarColor(panelConfig.PanelHandle, AppSettingData.ApplicationSetting.PopOutSetting.PopOutTitleBarCustomization.HexColor); } } + + if(ActiveProfile.PanelConfigs.Any(p => p.AlwaysOnTop)) + WindowActionManager.ApplyAlwaysOnTop(WindowProcessManager.SimulatorProcess.Handle, PanelType.FlightSimMainWindow, true); } private async Task StepPostPopout() diff --git a/SimconnectAgent/FpsCalc.cs b/SimconnectAgent/FpsCalc.cs index 6aff9e5..c4baff4 100644 --- a/SimconnectAgent/FpsCalc.cs +++ b/SimconnectAgent/FpsCalc.cs @@ -5,32 +5,46 @@ namespace MSFSPopoutPanelManager.SimConnectAgent { public class FpsCalc { - private const int FpsLen = 25; - private static readonly float[] FpsStatistic = new float[FpsLen]; + private const int FPS_LEN = 20; + private static readonly float[] FpsStatistic = new float[FPS_LEN]; private static int _fpsIndex = -1; + private static int _avgFps; public static int GetAverageFps(int newValue) { if (_fpsIndex == -1) { - for (var i = 0; i < FpsLen; i++) + // initialize FpsStatistic array + for (var i = 0; i < FPS_LEN; i++) FpsStatistic[i] = newValue; - + + _avgFps = Convert.ToInt32(newValue); _fpsIndex = 1; } else { + var deltaFps = newValue - _avgFps; + + if (deltaFps < 0 && Math.Abs(deltaFps) > _avgFps * 0.1) // FPS suddenly drops more than 10% + { + newValue += Math.Abs(deltaFps) / 2; // Let the new FPS to be only half the delta drop + } + FpsStatistic[_fpsIndex] = newValue; _fpsIndex++; - if (_fpsIndex >= FpsLen) + if (_fpsIndex >= FPS_LEN) _fpsIndex = 0; + + _avgFps = Convert.ToInt32(FpsStatistic.Sum() / FPS_LEN); } + + return _avgFps; + } - var fps = 0; - if (_fpsIndex != -1) - fps = Convert.ToInt32(FpsStatistic.Sum() / FpsLen); - - return fps; + public static void Reset() + { + _fpsIndex = -1; + _avgFps = 0; } } } From a7c995922b5fd202a7c581ed74031959e6cf9f64 Mon Sep 17 00:00:00 2001 From: hawkeye Date: Tue, 17 Sep 2024 10:42:07 -0400 Subject: [PATCH 2/7] Update switch window --- DomainModel/DomainModel.csproj | 6 +- DomainModel/Profile/PanelConfig.cs | 7 +- DomainModel/Profile/PanelType.cs | 1 + DomainModel/Profile/ProfileSetting.cs | 2 + DomainModel/Profile/SwitchWindowConfig.cs | 9 +++ MainApp/App.xaml.cs | 1 + .../AppUserControl/PopOutPanelConfigCard.xaml | 2 +- MainApp/AppUserControl/ProfileCard.xaml | 11 +++ MainApp/AppUserControl/ProfileCard.xaml.cs | 19 +++-- MainApp/AppWindow/SwitchWindow.xaml | 69 +++++++++++++++++++ MainApp/AppWindow/SwitchWindow.xaml.cs | 65 +++++++++++++++++ MainApp/MainApp.csproj | 6 +- .../Styles/CustomMaterialDesignExpander.xaml | 2 +- MainApp/ViewModel/OrchestratorUIHelper.cs | 19 +++++ MainApp/ViewModel/ProfileCardViewModel.cs | 35 +++++++++- MainApp/ViewModel/SwitchWindowViewModel.cs | 37 ++++++++++ Orchestration/DynamicLodOrchestrator.cs | 4 +- Orchestration/Orchestration.csproj | 6 +- Orchestration/PanelPopOutOrchestrator.cs | 17 ++++- Shared/Shared.csproj | 6 +- SimconnectAgent/SimconnectAgent.csproj | 6 +- WindowsAgent/PInvoke.cs | 20 ++++++ WindowsAgent/WindowActionManager.cs | 5 +- WindowsAgent/WindowsAgent.csproj | 6 +- 24 files changed, 330 insertions(+), 31 deletions(-) create mode 100644 DomainModel/Profile/SwitchWindowConfig.cs create mode 100644 MainApp/AppWindow/SwitchWindow.xaml create mode 100644 MainApp/AppWindow/SwitchWindow.xaml.cs create mode 100644 MainApp/ViewModel/SwitchWindowViewModel.cs diff --git a/DomainModel/DomainModel.csproj b/DomainModel/DomainModel.csproj index 591a6a0..6848d72 100644 --- a/DomainModel/DomainModel.csproj +++ b/DomainModel/DomainModel.csproj @@ -11,9 +11,9 @@ https://github.com/hawkeye-stan/msfs-popout-panel-manager MSFSPopoutPanelManager.DomainModel x64 - 4.1.1.0 - 4.1.1.0 - 4.1.1.0 + 4.1.2.0 + 4.1.2.0 + 4.1.2.0 win-x64 Embedded Debug;Release;Local diff --git a/DomainModel/Profile/PanelConfig.cs b/DomainModel/Profile/PanelConfig.cs index 26fe447..5f9a89c 100644 --- a/DomainModel/Profile/PanelConfig.cs +++ b/DomainModel/Profile/PanelConfig.cs @@ -94,11 +94,11 @@ namespace MSFSPopoutPanelManager.DomainModel.Profile [JsonIgnore] public bool IsDeletablePanel => PanelType != PanelType.HudBarWindow && PanelType != PanelType.RefocusDisplay && - PanelType != PanelType.NumPadWindow; + PanelType != PanelType.NumPadWindow && PanelType != PanelType.SwitchWindow; [JsonIgnore] public bool IsTouchEnablePanel => PanelType != PanelType.HudBarWindow && PanelType != PanelType.RefocusDisplay && - PanelType != PanelType.NumPadWindow; + PanelType != PanelType.NumPadWindow && PanelType != PanelType.SwitchWindow; [JsonIgnore] public bool IsCustomPopOut => PanelType == PanelType.CustomPopout; @@ -116,6 +116,9 @@ namespace MSFSPopoutPanelManager.DomainModel.Profile [JsonIgnore] public bool IsNumPadWindow => PanelType == PanelType.NumPadWindow; + [JsonIgnore] + public bool IsSwitchWindow => PanelType == PanelType.SwitchWindow; + [JsonIgnore] public string PanelSourceCoordinateText { diff --git a/DomainModel/Profile/PanelType.cs b/DomainModel/Profile/PanelType.cs index 9fc1d9a..5b4943f 100644 --- a/DomainModel/Profile/PanelType.cs +++ b/DomainModel/Profile/PanelType.cs @@ -12,6 +12,7 @@ StatusMessageWindow = 7, RefocusDisplay = 8, NumPadWindow = 9, + SwitchWindow = 20, Unknown = 100 } } diff --git a/DomainModel/Profile/ProfileSetting.cs b/DomainModel/Profile/ProfileSetting.cs index d5157ea..85d4eca 100644 --- a/DomainModel/Profile/ProfileSetting.cs +++ b/DomainModel/Profile/ProfileSetting.cs @@ -18,5 +18,7 @@ namespace MSFSPopoutPanelManager.DomainModel.Profile public RefocusOnDisplay RefocusOnDisplay { get; set; } = new(); public NumPadConfig NumPadConfig { get; set; } = new(); + + public SwitchWindowConfig SwitchWindowConfig { get; set; } = new(); } } diff --git a/DomainModel/Profile/SwitchWindowConfig.cs b/DomainModel/Profile/SwitchWindowConfig.cs new file mode 100644 index 0000000..82d1057 --- /dev/null +++ b/DomainModel/Profile/SwitchWindowConfig.cs @@ -0,0 +1,9 @@ +using MSFSPopoutPanelManager.Shared; + +namespace MSFSPopoutPanelManager.DomainModel.Profile +{ + public class SwitchWindowConfig : ObservableObject + { + public bool IsEnabled { get; set; } = false; + } +} \ No newline at end of file diff --git a/MainApp/App.xaml.cs b/MainApp/App.xaml.cs index 6604a77..519d330 100644 --- a/MainApp/App.xaml.cs +++ b/MainApp/App.xaml.cs @@ -82,6 +82,7 @@ namespace MSFSPopoutPanelManager.MainApp services.AddTransient(s => new MessageWindowViewModel(SharedStorage, s.GetRequiredService(), s.GetRequiredService())); services.AddTransient(s => new HudBarViewModel(SharedStorage, s.GetRequiredService())); services.AddTransient(_ => new NumPadViewModel(SharedStorage)); + services.AddTransient(_ => new SwitchWindowViewModel(SharedStorage)); }).Build(); diff --git a/MainApp/AppUserControl/PopOutPanelConfigCard.xaml b/MainApp/AppUserControl/PopOutPanelConfigCard.xaml index 6e176c2..f6e17dd 100644 --- a/MainApp/AppUserControl/PopOutPanelConfigCard.xaml +++ b/MainApp/AppUserControl/PopOutPanelConfigCard.xaml @@ -224,7 +224,7 @@ x:Name="StackPanelAdjustment" Width="440" Orientation="Horizontal" - Visibility="{c:Binding 'DataItem.IsBuiltInPopOut or DataItem.IsHudBarWindow or DataItem.IsNumPadWindow or (DataItem.IsCustomPopOut and DataItem.PanelSource.X != null)'}"> + Visibility="{c:Binding 'DataItem.IsBuiltInPopOut or DataItem.IsHudBarWindow or DataItem.IsNumPadWindow or DataItem.IsSwitchWindow or (DataItem.IsCustomPopOut and DataItem.PanelSource.X != null)'}"> Include in-game menu bar panels for pop out management and touch screen support + Add a virtual keyboard NumPad + + + Add a switch window command bar + + (); Loaded += (_, _) => { DataContext = _viewModel; }; + +#if LOCAL + this.wrapPanelSwitchWindow.Visibility = Visibility.Visible; +#else + this.wrapPanelSwitchWindow.Visibility = Visibility.Collapsed; +#endif } private void ToggleButtonEditProfileTitle_Click(object sender, RoutedEventArgs e) @@ -46,22 +52,27 @@ namespace MSFSPopoutPanelManager.MainApp.AppUserControl private void IncludeInGamePanel_TargetUpdated(object sender, DataTransferEventArgs e) { - _viewModel.IncludeInGamePanelUpdatedCommand.Execute(null); + _viewModel.IncludeInGamePanelUpdatedCommand?.Execute(null); } private void AddHudBar_TargetUpdated(object sender, DataTransferEventArgs e) { - _viewModel.AddHudBarUpdatedCommand.Execute(null); + _viewModel.AddHudBarUpdatedCommand?.Execute(null); } private void AddRefocusDisplay_TargetUpdated(object sender, DataTransferEventArgs e) { - _viewModel.RefocusDisplayUpdatedCommand.Execute(null); + _viewModel.RefocusDisplayUpdatedCommand?.Execute(null); } private void AddNumPad_TargetUpdated(object sender, DataTransferEventArgs e) { - _viewModel.AddNumPadUpdatedCommand.Execute(null); + _viewModel.AddNumPadUpdatedCommand?.Execute(null); + } + + private void AddSwitchWindow_TargetUpdated(object sender, DataTransferEventArgs e) + { + _viewModel.AddSwitchWindowUpdatedCommand?.Execute(null); } } diff --git a/MainApp/AppWindow/SwitchWindow.xaml b/MainApp/AppWindow/SwitchWindow.xaml new file mode 100644 index 0000000..28e5ba1 --- /dev/null +++ b/MainApp/AppWindow/SwitchWindow.xaml @@ -0,0 +1,69 @@ + + + 28 + + + + + + + + + + + + + diff --git a/MainApp/AppWindow/SwitchWindow.xaml.cs b/MainApp/AppWindow/SwitchWindow.xaml.cs new file mode 100644 index 0000000..ded57ff --- /dev/null +++ b/MainApp/AppWindow/SwitchWindow.xaml.cs @@ -0,0 +1,65 @@ +using Microsoft.Extensions.DependencyInjection; +using MSFSPopoutPanelManager.MainApp.ViewModel; +using System; +using System.ComponentModel; +using System.Windows; +using System.Windows.Input; +using System.Windows.Interop; + +namespace MSFSPopoutPanelManager.MainApp.AppWindow +{ + /// + /// Interaction logic for SwitchWindow.xaml + /// + public partial class SwitchWindow : Window + { + private readonly SwitchWindowViewModel _viewModel; + + public SwitchWindow(Guid panelId, int initialWidth, int initialHeight) + { + InitializeComponent(); + if (DesignerProperties.GetIsInDesignMode(new DependencyObject())) + return; + + _viewModel = App.AppHost.Services.GetRequiredService(); + _viewModel.PanelId = panelId; + + Loaded += (_, _) => + { + DataContext = _viewModel; + + var window = Window.GetWindow(this); + if (window == null) + throw new ApplicationException("Unable to instantiate switchWindow window"); + + _viewModel.PanelConfig.PanelHandle = new WindowInteropHelper(window).Handle; + + if (initialWidth == 0 && initialHeight == 0) + { + this.Width = 410; + this.Height = 75; + _viewModel.PanelConfig.Width = Convert.ToInt16(this.Width); + _viewModel.PanelConfig.Height = Convert.ToInt32(this.Height); + } + else + { + this.Width = initialWidth; + this.Height = initialHeight; + } + }; + + this.MouseLeftButtonDown += SwitchWindow_MouseLeftButtonDown; + this.Topmost = true; + } + + private void SwitchWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + DragMove(); + } + + private void BtnClose_Click(object sender, RoutedEventArgs e) + { + this.Close(); + } + } +} diff --git a/MainApp/MainApp.csproj b/MainApp/MainApp.csproj index 4e2fcfc..7e2be53 100644 --- a/MainApp/MainApp.csproj +++ b/MainApp/MainApp.csproj @@ -14,9 +14,9 @@ MSFSPopoutPanelManager.MainApp logo.ico x64 - 4.1.1.0 - 4.1.1.0 - 4.1.1.0 + 4.1.2.0 + 4.1.2.0 + 4.1.2.0 embedded en diff --git a/MainApp/Styles/CustomMaterialDesignExpander.xaml b/MainApp/Styles/CustomMaterialDesignExpander.xaml index f8c3697..1e7932e 100644 --- a/MainApp/Styles/CustomMaterialDesignExpander.xaml +++ b/MainApp/Styles/CustomMaterialDesignExpander.xaml @@ -25,7 +25,7 @@ Kind="ChevronDown" Opacity="0.5" RenderTransformOrigin="0.5 0.5" - Visibility="{c:Binding '!DataItem.IsHudBarWindow and !DataItem.IsRefocusDisplay and !DataItem.IsNumPadWindow and !ActiveProfile.IsEditingPanelSource'}"> + Visibility="{c:Binding '!DataItem.IsHudBarWindow and !DataItem.IsRefocusDisplay and !DataItem.IsNumPadWindow and !DataItem.IsSwitchWindow and !ActiveProfile.IsEditingPanelSource'}"> diff --git a/MainApp/ViewModel/OrchestratorUIHelper.cs b/MainApp/ViewModel/OrchestratorUIHelper.cs index bd0bc66..20c2e51 100644 --- a/MainApp/ViewModel/OrchestratorUIHelper.cs +++ b/MainApp/ViewModel/OrchestratorUIHelper.cs @@ -36,6 +36,9 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel panelPopOutOrchestrator.OnNumPadOpened -= HandleOnNumPadOpened; panelPopOutOrchestrator.OnNumPadOpened += HandleOnNumPadOpened; + + panelPopOutOrchestrator.OnSwitchWindowOpened -= HandleOnSwitchWindowOpened; + panelPopOutOrchestrator.OnSwitchWindowOpened += HandleOnSwitchWindowOpened; } private void HandleShowOverlay(object sender, PanelConfig panelConfig) @@ -99,6 +102,22 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel }); } + private void HandleOnSwitchWindowOpened(object sender, PanelConfig panelConfig) + { + Application.Current.Dispatcher.Invoke(async () => + { + var switchWindow = new SwitchWindow(panelConfig.Id, panelConfig.Width, panelConfig.Height); + switchWindow.Show(); + + await Task.Run(() => + { + Thread.Sleep(1000); + WindowActionManager.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height); + WindowActionManager.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height); + }); + }); + } + private void HandleOnPopOutStarted(object sender, EventArgs e) { if (!AppSettingData.ApplicationSetting.PopOutSetting.MinimizeDuringPopOut) diff --git a/MainApp/ViewModel/ProfileCardViewModel.cs b/MainApp/ViewModel/ProfileCardViewModel.cs index c93c74f..1084705 100644 --- a/MainApp/ViewModel/ProfileCardViewModel.cs +++ b/MainApp/ViewModel/ProfileCardViewModel.cs @@ -41,6 +41,8 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel public ICommand AddNumPadUpdatedCommand { get; } + public ICommand AddSwitchWindowUpdatedCommand { get; } + public ICommand RefocusDisplayRefreshedCommand { get; } public DelegateCommand RefocusDisplaySelectionUpdatedCommand { get; } @@ -100,7 +102,9 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel AddHudBarUpdatedCommand = new DelegateCommand(OnAddHudBarUpdated); AddNumPadUpdatedCommand = new DelegateCommand(OnAddNumPadUpdated); - +#if LOCAL + AddSwitchWindowUpdatedCommand = new DelegateCommand(OnAddSwitchWindowUpdated); +#endif RefocusDisplayUpdatedCommand = new DelegateCommand(OnRefocusDisplayUpdated); RefocusDisplayRefreshedCommand = new DelegateCommand(OnRefocusDisplayRefreshed); @@ -239,6 +243,35 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel } } + private void OnAddSwitchWindowUpdated() + { + if (ActiveProfile == null) + return; + + + if (ActiveProfile.ProfileSetting.SwitchWindowConfig.IsEnabled) + { + if (ActiveProfile.PanelConfigs.Any(p => p.PanelType == PanelType.SwitchWindow)) + return; + + ActiveProfile.PanelConfigs.Add(new PanelConfig + { + PanelName = "Switch Window", + PanelType = PanelType.SwitchWindow, + Left = 0, + Top = 0, + Width = 0, + Height = 0, + AutoGameRefocus = false + }); + } + else + { + ActiveProfile.PanelConfigs.RemoveAll(p => p.PanelType == PanelType.SwitchWindow); + } + + } + private void OnRefocusDisplayUpdated() { if (ActiveProfile == null) diff --git a/MainApp/ViewModel/SwitchWindowViewModel.cs b/MainApp/ViewModel/SwitchWindowViewModel.cs new file mode 100644 index 0000000..ad8a58c --- /dev/null +++ b/MainApp/ViewModel/SwitchWindowViewModel.cs @@ -0,0 +1,37 @@ +using System; +using System.Linq; +using MSFSPopoutPanelManager.DomainModel.Profile; +using MSFSPopoutPanelManager.Orchestration; +using MSFSPopoutPanelManager.WindowsAgent; +using Prism.Commands; + +namespace MSFSPopoutPanelManager.MainApp.ViewModel +{ + public class SwitchWindowViewModel : BaseViewModel + { + public DelegateCommand ButtonCommand { get; private set; } + + public Guid PanelId { get; set; } + + public PanelConfig PanelConfig => ActiveProfile.PanelConfigs.FirstOrDefault(p => p.Id == PanelId); + + + public SwitchWindowViewModel(SharedStorage sharedStorage) : base(sharedStorage) + { + ButtonCommand = new DelegateCommand(OnButtonActivated); + } + + private void OnButtonActivated(string commandParameter) + { + switch (commandParameter) + { + case "VerticalPanel": + PInvoke.SwitchToThisWindow(PInvoke.GetWindowHandle("737 Instruments Vertical"), true); + break; + case "OverheadPanel": + PInvoke.SwitchToThisWindow(PInvoke.GetWindowHandle("737 Instruments Overhead"), true); + break; + } + } + } +} diff --git a/Orchestration/DynamicLodOrchestrator.cs b/Orchestration/DynamicLodOrchestrator.cs index 0d7a02f..f304014 100644 --- a/Orchestration/DynamicLodOrchestrator.cs +++ b/Orchestration/DynamicLodOrchestrator.cs @@ -133,7 +133,7 @@ namespace MSFSPopoutPanelManager.Orchestration if (!FlightSimData.IsFlightStarted || !FlightSimData.IsInCockpit) return; - if (DateTime.Now - _lastLodUpdateTime <= TimeSpan.FromSeconds(1)) + if (DateTime.Now - _lastLodUpdateTime <= TimeSpan.FromSeconds(3)) return; var deltaFps = DynamicLodSimData.Fps - DynamicLodSetting.TargetedFps; @@ -239,7 +239,7 @@ namespace MSFSPopoutPanelManager.Orchestration private void SetTlod(int deltaFps) { - var tlodStep = Math.Max(5, Math.Abs(deltaFps / 2)); + var tlodStep = Math.Max(10, Math.Abs(deltaFps / 2)); var newTlod = DynamicLodSimData.Tlod + Math.Sign(deltaFps) * tlodStep; if (DynamicLodSetting.TlodMinOnGround && DynamicLodSimData.AltAboveGround <= DynamicLodSetting.AltTlodBase) diff --git a/Orchestration/Orchestration.csproj b/Orchestration/Orchestration.csproj index 6cf921a..fac2f5f 100644 --- a/Orchestration/Orchestration.csproj +++ b/Orchestration/Orchestration.csproj @@ -11,9 +11,9 @@ https://github.com/hawkeye-stan/msfs-popout-panel-manager MSFSPopoutPanelManager.Orchestration x64 - 4.1.1.0 - 4.1.1.0 - 4.1.1.0 + 4.1.2.0 + 4.1.2.0 + 4.1.2.0 win-x64 Embedded Debug;Release;Local diff --git a/Orchestration/PanelPopOutOrchestrator.cs b/Orchestration/PanelPopOutOrchestrator.cs index 744fbfc..015d779 100644 --- a/Orchestration/PanelPopOutOrchestrator.cs +++ b/Orchestration/PanelPopOutOrchestrator.cs @@ -50,6 +50,7 @@ namespace MSFSPopoutPanelManager.Orchestration public event EventHandler OnPopOutCompleted; public event EventHandler OnHudBarOpened; public event EventHandler OnNumPadOpened; + public event EventHandler OnSwitchWindowOpened; public async Task ManualPopOut() { @@ -122,7 +123,9 @@ namespace MSFSPopoutPanelManager.Orchestration StepAddHudBar(); StepAddNumPad(); - + + StepAddSwitchWindow(); + SetupRefocusDisplay(); StepApplyPanelConfig(); @@ -390,6 +393,18 @@ namespace MSFSPopoutPanelManager.Orchestration }); } + private void StepAddSwitchWindow() + { + if (!ActiveProfile.ProfileSetting.SwitchWindowConfig.IsEnabled) + return; + + WorkflowStepWithMessage.Execute("Opening Switch Window", () => + { + var panelConfig = ActiveProfile.PanelConfigs.FirstOrDefault(p => p.PanelType == PanelType.SwitchWindow); + OnSwitchWindowOpened?.Invoke(this, panelConfig); + }); + } + public void SetupRefocusDisplay() { if (!ActiveProfile.ProfileSetting.RefocusOnDisplay.IsEnabled) diff --git a/Shared/Shared.csproj b/Shared/Shared.csproj index 08c68ae..1c410bb 100644 --- a/Shared/Shared.csproj +++ b/Shared/Shared.csproj @@ -11,9 +11,9 @@ https://github.com/hawkeye-stan/msfs-popout-panel-manager MSFSPopoutPanelManager.Shared x64 - 4.1.1.0 - 4.1.1.0 - 4.1.1.0 + 4.1.2.0 + 4.1.2.0 + 4.1.2.0 win-x64 Embedded Debug;Release;Local diff --git a/SimconnectAgent/SimconnectAgent.csproj b/SimconnectAgent/SimconnectAgent.csproj index 818840d..7ca62cf 100644 --- a/SimconnectAgent/SimconnectAgent.csproj +++ b/SimconnectAgent/SimconnectAgent.csproj @@ -11,9 +11,9 @@ https://github.com/hawkeye-stan/msfs-popout-panel-manager MSFSPopoutPanelManager.SimConnectAgent x64 - 4.1.1.0 - 4.1.1.0 - 4.1.1.0 + 4.1.2.0 + 4.1.2.0 + 4.1.2.0 win-x64 Embedded Debug;Release;Local diff --git a/WindowsAgent/PInvoke.cs b/WindowsAgent/PInvoke.cs index 97a7909..5461970 100644 --- a/WindowsAgent/PInvoke.cs +++ b/WindowsAgent/PInvoke.cs @@ -143,6 +143,9 @@ namespace MSFSPopoutPanelManager.WindowsAgent [DllImport("user32.dll", SetLastError = true)] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); + [DllImport("user32.dll", SetLastError = true)] + public static extern void SwitchToThisWindow(IntPtr hWnd, bool turnOn); + [DllImport("user32.dll", SetLastError = true)] public static extern int UnhookWinEvent(IntPtr hWinEventHook); @@ -193,6 +196,23 @@ namespace MSFSPopoutPanelManager.WindowsAgent return new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top); } + + public static IntPtr GetWindowHandle(string windowCaption) + { + IntPtr windowHandle = IntPtr.Zero; + + EnumWindows((hwnd, _) => + { + var caption = GetWindowText(hwnd); + + if (caption == windowCaption) + windowHandle = hwnd; + + return true; + }, 0); + + return windowHandle; + } } public struct RECT diff --git a/WindowsAgent/WindowActionManager.cs b/WindowsAgent/WindowActionManager.cs index ffd5a8c..9ea692d 100644 --- a/WindowsAgent/WindowActionManager.cs +++ b/WindowsAgent/WindowActionManager.cs @@ -181,6 +181,9 @@ namespace MSFSPopoutPanelManager.WindowsAgent if (caption.IndexOf("Virtual NumPad", StringComparison.Ordinal) > -1) return PanelType.NumPadWindow; + + if (caption.IndexOf("Switch Window", StringComparison.Ordinal) > -1) + return PanelType.SwitchWindow; return PanelType.PopOutManager; } @@ -194,7 +197,7 @@ namespace MSFSPopoutPanelManager.WindowsAgent { var panelType = GetWindowPanelType(hwnd); - if (panelType == PanelType.CustomPopout || panelType == PanelType.HudBarWindow || panelType == PanelType.NumPadWindow) + if (panelType == PanelType.CustomPopout || panelType == PanelType.HudBarWindow || panelType == PanelType.NumPadWindow || panelType == PanelType.SwitchWindow) CloseWindow(hwnd); return true; diff --git a/WindowsAgent/WindowsAgent.csproj b/WindowsAgent/WindowsAgent.csproj index 337f6b8..c8f4d3d 100644 --- a/WindowsAgent/WindowsAgent.csproj +++ b/WindowsAgent/WindowsAgent.csproj @@ -11,9 +11,9 @@ https://github.com/hawkeye-stan/msfs-popout-panel-manager MSFSPopoutPanelManager.WindowsAgent x64 - 4.1.1.0 - 4.1.1.0 - 4.1.1.0 + 4.1.2.0 + 4.1.2.0 + 4.1.2.0 win-x64 Embedded Debug;Release;Local From 6cb154abe97cc9011ea89edfbbedfd15e5c280c8 Mon Sep 17 00:00:00 2001 From: hawkeye Date: Tue, 17 Sep 2024 17:33:23 -0400 Subject: [PATCH 3/7] Update code --- DomainModel/Profile/FloatingPanel.cs | 2 +- DomainModel/Profile/SwitchWindowConfig.cs | 12 ++++++++- MainApp/AppUserControl/ProfileCard.xaml | 2 +- MainApp/AppUserControl/ProfileCard.xaml.cs | 6 ++--- MainApp/AppWindow/SwitchWindow.xaml | 22 +--------------- MainApp/AppWindow/SwitchWindow.xaml.cs | 29 +++++++++++++++++++--- MainApp/ViewModel/ProfileCardViewModel.cs | 3 +-- MainApp/ViewModel/SwitchWindowViewModel.cs | 13 +++------- 8 files changed, 47 insertions(+), 42 deletions(-) diff --git a/DomainModel/Profile/FloatingPanel.cs b/DomainModel/Profile/FloatingPanel.cs index 8c91a7a..2a6767e 100644 --- a/DomainModel/Profile/FloatingPanel.cs +++ b/DomainModel/Profile/FloatingPanel.cs @@ -8,7 +8,7 @@ namespace MSFSPopoutPanelManager.DomainModel.Profile { public FloatingPanel() { - PropertyChanged += FloatingPanel_PropertyChanged; ; + PropertyChanged += FloatingPanel_PropertyChanged; } private void FloatingPanel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) diff --git a/DomainModel/Profile/SwitchWindowConfig.cs b/DomainModel/Profile/SwitchWindowConfig.cs index 82d1057..cbc0aa5 100644 --- a/DomainModel/Profile/SwitchWindowConfig.cs +++ b/DomainModel/Profile/SwitchWindowConfig.cs @@ -1,9 +1,19 @@ -using MSFSPopoutPanelManager.Shared; +using System.Collections.Generic; +using MSFSPopoutPanelManager.Shared; namespace MSFSPopoutPanelManager.DomainModel.Profile { public class SwitchWindowConfig : ObservableObject { public bool IsEnabled { get; set; } = false; + + public List Panels { get; set; } + } + + public class SwitchWindowPanel + { + public string DisplayName { get; set; } + + public string PanelCaption { get; set; } } } \ No newline at end of file diff --git a/MainApp/AppUserControl/ProfileCard.xaml b/MainApp/AppUserControl/ProfileCard.xaml index 7974c6f..1e0db90 100644 --- a/MainApp/AppUserControl/ProfileCard.xaml +++ b/MainApp/AppUserControl/ProfileCard.xaml @@ -267,7 +267,7 @@ Add a virtual keyboard NumPad - + - - - - - - diff --git a/MainApp/AppWindow/SwitchWindow.xaml.cs b/MainApp/AppWindow/SwitchWindow.xaml.cs deleted file mode 100644 index 60e9138..0000000 --- a/MainApp/AppWindow/SwitchWindow.xaml.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using MSFSPopoutPanelManager.MainApp.ViewModel; -using System; -using System.ComponentModel; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Interop; -using System.Windows.Media; - -namespace MSFSPopoutPanelManager.MainApp.AppWindow -{ - public partial class SwitchWindow : Window - { - private readonly SwitchWindowViewModel _viewModel; - - public SwitchWindow(Guid panelId, int initialWidth, int initialHeight) - { - InitializeComponent(); - if (DesignerProperties.GetIsInDesignMode(new DependencyObject())) - return; - - _viewModel = App.AppHost.Services.GetRequiredService(); - _viewModel.PanelId = panelId; - - Loaded += (_, _) => - { - DataContext = _viewModel; - - var window = Window.GetWindow(this); - if (window == null) - throw new ApplicationException("Unable to instantiate switchWindow window"); - - _viewModel.PanelConfig.PanelHandle = new WindowInteropHelper(window).Handle; - - if (initialWidth == 0 && initialHeight == 0) - { - this.Width = 410; - this.Height = 60; - _viewModel.PanelConfig.Width = Convert.ToInt16(this.Width); - _viewModel.PanelConfig.Height = Convert.ToInt32(this.Height); - } - else - { - this.Width = initialWidth; - this.Height = initialHeight; - } - }; - - this.MouseLeftButtonDown += SwitchWindow_MouseLeftButtonDown; - this.Topmost = true; - - if (_viewModel.ProfileData.ActiveProfile.ProfileSetting.SwitchWindowConfig.Panels != null) - { - var style = Application.Current.TryFindResource("MaterialDesignOutlinedButton") as Style; - - WrapPanelCustomButtons.Children.Clear(); - - foreach (var panel in _viewModel.ProfileData.ActiveProfile.ProfileSetting.SwitchWindowConfig.Panels) - { - WrapPanelCustomButtons.Children.Add(new Button() - { - Height = 45, - Margin = new Thickness(5, 5, 5, 5), - Content = panel.DisplayName, - Foreground = new SolidColorBrush(Colors.White), - FontSize = 28, - Style = style, - Command = _viewModel.ButtonCommand, - CommandParameter = panel.PanelCaption - }); - } - } - } - - private void SwitchWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - DragMove(); - } - - private void BtnClose_Click(object sender, RoutedEventArgs e) - { - this.Close(); - } - } -} diff --git a/MainApp/Styles/CustomMaterialDesignExpander.xaml b/MainApp/Styles/CustomMaterialDesignExpander.xaml index 1e7932e..f8c3697 100644 --- a/MainApp/Styles/CustomMaterialDesignExpander.xaml +++ b/MainApp/Styles/CustomMaterialDesignExpander.xaml @@ -25,7 +25,7 @@ Kind="ChevronDown" Opacity="0.5" RenderTransformOrigin="0.5 0.5" - Visibility="{c:Binding '!DataItem.IsHudBarWindow and !DataItem.IsRefocusDisplay and !DataItem.IsNumPadWindow and !DataItem.IsSwitchWindow and !ActiveProfile.IsEditingPanelSource'}"> + Visibility="{c:Binding '!DataItem.IsHudBarWindow and !DataItem.IsRefocusDisplay and !DataItem.IsNumPadWindow and !ActiveProfile.IsEditingPanelSource'}"> diff --git a/MainApp/ViewModel/OrchestratorUIHelper.cs b/MainApp/ViewModel/OrchestratorUIHelper.cs index 20c2e51..bd0bc66 100644 --- a/MainApp/ViewModel/OrchestratorUIHelper.cs +++ b/MainApp/ViewModel/OrchestratorUIHelper.cs @@ -36,9 +36,6 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel panelPopOutOrchestrator.OnNumPadOpened -= HandleOnNumPadOpened; panelPopOutOrchestrator.OnNumPadOpened += HandleOnNumPadOpened; - - panelPopOutOrchestrator.OnSwitchWindowOpened -= HandleOnSwitchWindowOpened; - panelPopOutOrchestrator.OnSwitchWindowOpened += HandleOnSwitchWindowOpened; } private void HandleShowOverlay(object sender, PanelConfig panelConfig) @@ -102,22 +99,6 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel }); } - private void HandleOnSwitchWindowOpened(object sender, PanelConfig panelConfig) - { - Application.Current.Dispatcher.Invoke(async () => - { - var switchWindow = new SwitchWindow(panelConfig.Id, panelConfig.Width, panelConfig.Height); - switchWindow.Show(); - - await Task.Run(() => - { - Thread.Sleep(1000); - WindowActionManager.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height); - WindowActionManager.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height); - }); - }); - } - private void HandleOnPopOutStarted(object sender, EventArgs e) { if (!AppSettingData.ApplicationSetting.PopOutSetting.MinimizeDuringPopOut) diff --git a/MainApp/ViewModel/ProfileCardViewModel.cs b/MainApp/ViewModel/ProfileCardViewModel.cs index 6bfbf1e..c93c74f 100644 --- a/MainApp/ViewModel/ProfileCardViewModel.cs +++ b/MainApp/ViewModel/ProfileCardViewModel.cs @@ -41,8 +41,6 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel public ICommand AddNumPadUpdatedCommand { get; } - public ICommand AddSwitchWindowUpdatedCommand { get; } - public ICommand RefocusDisplayRefreshedCommand { get; } public DelegateCommand RefocusDisplaySelectionUpdatedCommand { get; } @@ -102,9 +100,7 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel AddHudBarUpdatedCommand = new DelegateCommand(OnAddHudBarUpdated); AddNumPadUpdatedCommand = new DelegateCommand(OnAddNumPadUpdated); -#if LOCAL - AddSwitchWindowUpdatedCommand = new DelegateCommand(OnAddSwitchWindowUpdated); -#endif + RefocusDisplayUpdatedCommand = new DelegateCommand(OnRefocusDisplayUpdated); RefocusDisplayRefreshedCommand = new DelegateCommand(OnRefocusDisplayRefreshed); @@ -243,34 +239,6 @@ namespace MSFSPopoutPanelManager.MainApp.ViewModel } } - private void OnAddSwitchWindowUpdated() - { - if (ActiveProfile == null) - return; - - if (ActiveProfile.ProfileSetting.SwitchWindowConfig.IsEnabled) - { - if (ActiveProfile.PanelConfigs.Any(p => p.PanelType == PanelType.SwitchWindow)) - return; - - ActiveProfile.PanelConfigs.Add(new PanelConfig - { - PanelName = "Switch Window", - PanelType = PanelType.SwitchWindow, - Left = 0, - Top = 0, - Width = 0, - Height = 0, - AutoGameRefocus = false - }); - } - else - { - ActiveProfile.PanelConfigs.RemoveAll(p => p.PanelType == PanelType.SwitchWindow); - ActiveProfile.ProfileSetting.SwitchWindowConfig.Panels = null; - } - } - private void OnRefocusDisplayUpdated() { if (ActiveProfile == null) diff --git a/MainApp/ViewModel/SwitchWindowViewModel.cs b/MainApp/ViewModel/SwitchWindowViewModel.cs deleted file mode 100644 index 9bd8e76..0000000 --- a/MainApp/ViewModel/SwitchWindowViewModel.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Linq; -using MSFSPopoutPanelManager.DomainModel.Profile; -using MSFSPopoutPanelManager.Orchestration; -using MSFSPopoutPanelManager.WindowsAgent; -using Prism.Commands; - -namespace MSFSPopoutPanelManager.MainApp.ViewModel -{ - public class SwitchWindowViewModel : BaseViewModel - { - public DelegateCommand ButtonCommand { get; private set; } - - public Guid PanelId { get; set; } - - public PanelConfig PanelConfig => ActiveProfile.PanelConfigs.FirstOrDefault(p => p.Id == PanelId); - - - public SwitchWindowViewModel(SharedStorage sharedStorage) : base(sharedStorage) - { - ButtonCommand = new DelegateCommand(OnButtonActivated); - } - - private void OnButtonActivated(string commandParameter) - { - var handle = PInvoke.GetWindowHandle(commandParameter); - - if(handle != IntPtr.Zero) - PInvoke.SwitchToThisWindow(handle, true); - } - } -} diff --git a/Orchestration/PanelConfigurationOrchestrator.cs b/Orchestration/PanelConfigurationOrchestrator.cs index 7589b03..2c554c7 100644 --- a/Orchestration/PanelConfigurationOrchestrator.cs +++ b/Orchestration/PanelConfigurationOrchestrator.cs @@ -130,8 +130,15 @@ namespace MSFSPopoutPanelManager.Orchestration { InputEmulationManager.ToggleFullScreenPanel(panelConfig.PanelHandle); - if (!panelConfig.FullScreen) + if (panelConfig.FullScreen) + { + WindowActionManager.SetHostMonitor(panelConfig); + } + else + { WindowActionManager.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height); + panelConfig.FullScreenMonitorInfo = null; + } } else if (configPropertyName == PanelConfigPropertyName.PanelName) { diff --git a/Orchestration/PanelPopOutOrchestrator.cs b/Orchestration/PanelPopOutOrchestrator.cs index 422ce0b..749890f 100644 --- a/Orchestration/PanelPopOutOrchestrator.cs +++ b/Orchestration/PanelPopOutOrchestrator.cs @@ -50,7 +50,6 @@ namespace MSFSPopoutPanelManager.Orchestration public event EventHandler OnPopOutCompleted; public event EventHandler OnHudBarOpened; public event EventHandler OnNumPadOpened; - public event EventHandler OnSwitchWindowOpened; public async Task ManualPopOut() { @@ -124,8 +123,6 @@ namespace MSFSPopoutPanelManager.Orchestration StepAddNumPad(); - StepAddSwitchWindow(); - SetupRefocusDisplay(); StepApplyPanelConfig(); @@ -393,18 +390,6 @@ namespace MSFSPopoutPanelManager.Orchestration }); } - private void StepAddSwitchWindow() - { - if (!ActiveProfile.ProfileSetting.SwitchWindowConfig.IsEnabled) - return; - - WorkflowStepWithMessage.Execute("Opening Switch Window", () => - { - var panelConfig = ActiveProfile.PanelConfigs.FirstOrDefault(p => p.PanelType == PanelType.SwitchWindow); - OnSwitchWindowOpened?.Invoke(this, panelConfig); - }); - } - public void SetupRefocusDisplay() { if (!ActiveProfile.ProfileSetting.RefocusOnDisplay.IsEnabled) @@ -551,6 +536,9 @@ namespace MSFSPopoutPanelManager.Orchestration Thread.Sleep(500); InputEmulationManager.ToggleFullScreenPanel(panel.PanelHandle); Thread.Sleep(250); + + if (panel.TouchEnabled) + WindowActionManager.SetHostMonitor(panel); // Set full screen coordinate for touch } if (panel.FloatingPanel.IsEnabled && panel.FloatingPanel.HasKeyboardBinding && panel.FloatingPanel.IsHiddenOnStart) diff --git a/WindowsAgent/TouchEventManager.cs b/WindowsAgent/TouchEventManager.cs index 99c7640..8260e40 100644 --- a/WindowsAgent/TouchEventManager.cs +++ b/WindowsAgent/TouchEventManager.cs @@ -92,10 +92,8 @@ namespace MSFSPopoutPanelManager.WindowsAgent // If touch point is within pop out panel boundaries and have touch enabled var panelConfig = ActiveProfile.PanelConfigs.FirstOrDefault(p => p.TouchEnabled && - (info.pt.X > p.Left - && info.pt.X < p.Left + p.Width - && info.pt.Y > p.Top + (p.HideTitlebar ? 5 : PANEL_MENUBAR_HEIGHT) - && info.pt.Y < p.Top + p.Height)); + ((p.FullScreen && CheckWithinFullScreenCoordinate(p, info)) || CheckWithinWindowCoordinate(p, info))); + if (panelConfig == null) return PInvoke.CallNextHookEx(_hHook, code, wParam, lParam); @@ -218,5 +216,21 @@ namespace MSFSPopoutPanelManager.WindowsAgent return PInvoke.CallNextHookEx(_hHook, code, wParam, lParam); } + + private static bool CheckWithinWindowCoordinate(PanelConfig panelConfig, MSLLHOOKSTRUCT coor) + { + return coor.pt.X > panelConfig.Left + && coor.pt.X < panelConfig.Left + panelConfig.Width + && coor.pt.Y > panelConfig.Top + (panelConfig.HideTitlebar ? 5 : PANEL_MENUBAR_HEIGHT) + && coor.pt.Y < panelConfig.Top + panelConfig.Height; + } + + private static bool CheckWithinFullScreenCoordinate(PanelConfig panelConfig, MSLLHOOKSTRUCT coor) + { + return coor.pt.X > panelConfig.FullScreenMonitorInfo.X + && coor.pt.X < panelConfig.FullScreenMonitorInfo.X + panelConfig.FullScreenMonitorInfo.Width + && coor.pt.Y > panelConfig.FullScreenMonitorInfo.Y + && coor.pt.Y < panelConfig.FullScreenMonitorInfo.Y + panelConfig.FullScreenMonitorInfo.Height; + } } } diff --git a/WindowsAgent/WindowActionManager.cs b/WindowsAgent/WindowActionManager.cs index 7c33d57..2a1ffa6 100644 --- a/WindowsAgent/WindowActionManager.cs +++ b/WindowsAgent/WindowActionManager.cs @@ -183,9 +183,6 @@ namespace MSFSPopoutPanelManager.WindowsAgent if (caption.IndexOf("Virtual NumPad", StringComparison.Ordinal) > -1) return PanelType.NumPadWindow; - - if (caption.IndexOf("Switch Window", StringComparison.Ordinal) > -1) - return PanelType.SwitchWindow; return PanelType.PopOutManager; } @@ -199,7 +196,7 @@ namespace MSFSPopoutPanelManager.WindowsAgent { var panelType = GetWindowPanelType(hwnd); - if (panelType == PanelType.CustomPopout || panelType == PanelType.HudBarWindow || panelType == PanelType.NumPadWindow || panelType == PanelType.SwitchWindow) + if (panelType == PanelType.CustomPopout || panelType == PanelType.HudBarWindow || panelType == PanelType.NumPadWindow) CloseWindow(hwnd); return true; @@ -314,5 +311,22 @@ namespace MSFSPopoutPanelManager.WindowsAgent return text.Substring(0, 26).Equals("Microsoft Flight Simulator", StringComparison.InvariantCultureIgnoreCase); } + + public static void SetHostMonitor(PanelConfig panelConfig) + { + foreach (var screen in System.Windows.Forms.Screen.AllScreens) + { + if (screen.Bounds.IntersectsWith(new Rectangle(panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height))) + panelConfig.FullScreenMonitorInfo = + new MonitorInfo + { + Name = screen.DeviceName.Substring(screen.DeviceName.LastIndexOf("\\", StringComparison.Ordinal) + 1), + X = screen.Bounds.X, + Y = screen.Bounds.Y, + Width = screen.Bounds.Width, + Height = screen.Bounds.Height + }; + } + } } } From 0e0822970b93cfb78e5e14901c804aaddab1de65 Mon Sep 17 00:00:00 2001 From: hawkeye Date: Tue, 22 Oct 2024 23:21:13 -0400 Subject: [PATCH 7/7] Update release note --- .../PublishProfiles/FolderProfile.pubxml | 2 +- RELEASENOTES.md | 16 ++++------------ VERSION.md | 9 +++++++++ WindowsAgent/PInvoke.cs | 3 --- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/MainApp/Properties/PublishProfiles/FolderProfile.pubxml b/MainApp/Properties/PublishProfiles/FolderProfile.pubxml index 118e0a6..18dfaa2 100644 --- a/MainApp/Properties/PublishProfiles/FolderProfile.pubxml +++ b/MainApp/Properties/PublishProfiles/FolderProfile.pubxml @@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121. --> - Local + Release x64 ..\..\..\publish\master FileSystem diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5ad2bc7..c0a1df8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,15 +1,7 @@ -## Version 4.1.1 +## Version 4.1.2 -* Added option to store POPM profiles and configuration files in your user's AppData Roaming folder instead of Documents folder. Hopefully, this solved the issue where OneDrive users are having issue with POPM files. +* Added touch support for pop out when in full screen mode. -* Fixed POPM inability to close correctly when Keyboard Shortcuts preference is disabled. +* Fixed pop out always on top issue where it sometimes does not work. -* Fixed issue where auto start option failed to retain CommandLine arguments in exe.xml file. - -* Fixed issue where auto start does not work correctly for Steam version of MSFS since exe.xml file location has been moved by Steam installation. - -* Added ability for full screen panel to work as floating panel. An example use case is to show and hide EFB as full screen using keyboard shortcut. - -* Added dynamic LOD (my own implementation of AutoFPS) - this is totally experimental and unsupported. If you decide to use this version of dynamic LOD, you don't have to run multiple apps. - -* Fixed various smaller bugs. +* Improved dynamic LOD FPS detection and logic. diff --git a/VERSION.md b/VERSION.md index 1eabd21..ce54ff0 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1,6 +1,15 @@ # Version History
+## Version 4.1.2 + +* Added touch support for pop out when in full screen mode. + +* Fixed pop out always on top issue where it sometimes does not work. + +* Improved dynamic LOD FPS detection and logic. + + ## Version 4.1.1 * Added option to store POPM profiles and configuration files in your user's AppData Roaming folder instead of Documents folder. Hopefully, this solved the issue where OneDrive users are having issue with POPM files. diff --git a/WindowsAgent/PInvoke.cs b/WindowsAgent/PInvoke.cs index 5461970..fb74e56 100644 --- a/WindowsAgent/PInvoke.cs +++ b/WindowsAgent/PInvoke.cs @@ -143,9 +143,6 @@ namespace MSFSPopoutPanelManager.WindowsAgent [DllImport("user32.dll", SetLastError = true)] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); - [DllImport("user32.dll", SetLastError = true)] - public static extern void SwitchToThisWindow(IntPtr hWnd, bool turnOn); - [DllImport("user32.dll", SetLastError = true)] public static extern int UnhookWinEvent(IntPtr hWinEventHook);