1
0
Fork 0
mirror of https://github.com/hawkeye-stan/msfs-popout-panel-manager.git synced 2024-12-28 07:11:59 +00:00

Merge RSG GTN750 refocus fix

This commit is contained in:
Stanley 2022-09-30 09:49:42 -04:00
commit 023a474fda
7 changed files with 151 additions and 35 deletions

View file

@ -4,6 +4,8 @@ using MSFSPopoutPanelManager.WindowsAgent;
using System;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MSFSPopoutPanelManager.Orchestration
{
@ -14,6 +16,11 @@ namespace MSFSPopoutPanelManager.Orchestration
private Rectangle _lastWindowRectangle;
private IntPtr _panelHandleDisableRefresh = IntPtr.Zero;
private uint _prevWinEvent = PInvokeConstant.EVENT_SYSTEM_CAPTUREEND;
private int _winEventClickLock = 0;
private object _hookLock = new object();
private bool _isHookMouseDown = false;
public PanelConfigurationOrchestrator()
{
_winEvent = new PInvoke.WinEventProc(EventCallback);
@ -199,7 +206,10 @@ namespace MSFSPopoutPanelManager.Orchestration
return;
// Setup panel config event hooks
_winEventHook = PInvoke.SetWinEventHook(PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND, PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE, IntPtr.Zero, _winEvent, 0, 0, PInvokeConstant.WINEVENT_OUTOFCONTEXT);
if (!ActiveProfile.RealSimGearGTN750Gen1Override)
_winEventHook = PInvoke.SetWinEventHook(PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND, PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE, IntPtr.Zero, _winEvent, 0, 0, PInvokeConstant.WINEVENT_OUTOFCONTEXT);
else
_winEventHook = PInvoke.SetWinEventHook(PInvokeConstant.EVENT_SYSTEM_CAPTURESTART, PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE, IntPtr.Zero, _winEvent, 0, 0, PInvokeConstant.WINEVENT_OUTOFCONTEXT);
}
private void UnhookWinEvent()
@ -214,6 +224,8 @@ namespace MSFSPopoutPanelManager.Orchestration
{
case PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE:
case PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND:
case PInvokeConstant.EVENT_SYSTEM_CAPTURESTART:
case PInvokeConstant.EVENT_SYSTEM_CAPTUREEND:
// check by priority to speed up comparing of escaping constraints
if (hwnd == IntPtr.Zero || idObject != 0 || hWinEventHook != _winEventHook || !AllowEdit)
return;
@ -253,6 +265,17 @@ namespace MSFSPopoutPanelManager.Orchestration
PInvoke.ShowWindow(hwnd, PInvokeConstant.SW_RESTORE);
}
break;
case PInvokeConstant.EVENT_SYSTEM_CAPTURESTART:
if (!panelConfig.HasTouchableEvent || _prevWinEvent == PInvokeConstant.EVENT_SYSTEM_CAPTURESTART)
break;
HandleTouchDownEvent(panelConfig);
break;
case PInvokeConstant.EVENT_SYSTEM_CAPTUREEND:
if (!panelConfig.TouchEnabled || _prevWinEvent == PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE)
break;
HandleTouchUpEvent(panelConfig);
break;
}
}
else
@ -301,6 +324,75 @@ namespace MSFSPopoutPanelManager.Orchestration
case PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND:
ProfileData.WriteProfiles();
break;
case PInvokeConstant.EVENT_SYSTEM_CAPTURESTART:
if (!panelConfig.HasTouchableEvent || _prevWinEvent == PInvokeConstant.EVENT_SYSTEM_CAPTURESTART)
break;
HandleTouchDownEvent(panelConfig);
break;
case PInvokeConstant.EVENT_SYSTEM_CAPTUREEND:
if (!panelConfig.TouchEnabled || _prevWinEvent == PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE)
break;
HandleTouchUpEvent(panelConfig);
break;
}
}
}
private void HandleTouchDownEvent(PanelConfig panelConfig)
{
if (!_isHookMouseDown)
{
lock (_hookLock)
{
Point point;
PInvoke.GetCursorPos(out point);
// Disable left clicking if user is touching the title bar area
if (point.Y - panelConfig.Top > (panelConfig.HideTitlebar ? 5 : 31))
_isHookMouseDown = true;
}
}
}
private void HandleTouchUpEvent(PanelConfig panelConfig)
{
if (_isHookMouseDown)
{
Thread.Sleep(AppSettingData.AppSetting.TouchScreenSettings.TouchDownUpDelay);
lock (_hookLock)
{
_isHookMouseDown = false;
Point point;
PInvoke.GetCursorPos(out point);
// Disable left clicking if user is touching the title bar area
if (point.Y - panelConfig.Top > (panelConfig.HideTitlebar ? 5 : 31))
{
var prevWinEventClickLock = ++_winEventClickLock;
if (prevWinEventClickLock == _winEventClickLock && AppSettingData.AppSetting.TouchScreenSettings.RefocusGameWindow)
{
Task.Run(() => RefocusMsfs(panelConfig.PanelHandle, prevWinEventClickLock));
}
}
}
}
}
private void RefocusMsfs(IntPtr panelConfigHandle, int prevWinEventClickLock)
{
Thread.Sleep(AppSettingData.AppSetting.TouchScreenSettings.RefocusGameWindowDelay);
if (prevWinEventClickLock == _winEventClickLock)
{
if (!_isHookMouseDown)
{
var rectangle = WindowActionManager.GetWindowRect(panelConfigHandle);
PInvoke.SetCursorPos(rectangle.X - 5, rectangle.Y + 5);
}
}
}

View file

@ -140,6 +140,7 @@ namespace MSFSPopoutPanelManager.UserDataAgent
TouchDownUpDelay = 0;
RefocusGameWindow = true;
RefocusGameWindowDelay = 500;
RealSimGearGTN750Gen1Override = false;
}
public int TouchDownUpDelay { get; set; }
@ -147,6 +148,8 @@ namespace MSFSPopoutPanelManager.UserDataAgent
public bool RefocusGameWindow { get; set; }
public int RefocusGameWindowDelay { get; set; }
public bool RealSimGearGTN750Gen1Override { get; set; }
}
public class TouchPanelSettings : ObservableObject

View file

@ -16,6 +16,7 @@ namespace MSFSPopoutPanelManager.UserDataAgent
IsLocked = false;
PowerOnRequiredForColdStart = false;
IncludeInGamePanels = false;
RealSimGearGTN750Gen1Override = false;
MsfsGameWindowConfig = new MsfsGameWindowConfig();
@ -46,6 +47,8 @@ namespace MSFSPopoutPanelManager.UserDataAgent
public bool IncludeInGamePanels { get; set; }
public bool RealSimGearGTN750Gen1Override { get; set; }
public MsfsGameWindowConfig MsfsGameWindowConfig { get; set; }
[JsonIgnore]

View file

@ -16,6 +16,9 @@ namespace MSFSPopoutPanelManager.WindowsAgent
public const int SW_MINIMIZE = 6;
public const int SW_RESTORE = 9;
public const uint EVENT_SYSTEM_CAPTURESTART = 0x0008;
public const uint EVENT_SYSTEM_CAPTUREEND = 0x0009;
public const uint EVENT_SYSTEM_MOVESIZESTART = 0x000A;
public const uint EVENT_SYSTEM_MOVESIZEEND = 0x000B;
public const uint EVENT_OBJECT_LOCATIONCHANGE = 0x800B;

View file

@ -15,10 +15,9 @@ namespace MSFSPopoutPanelManager.WindowsAgent
private static PInvoke.WindowsHookExProc callbackDelegate = HookCallBack;
private static bool _isTouchDown;
private static int _mouseMoveCount;
private static bool _isMouseMoveBlock = false;
private static object _mouseTouchLock = new object();
private static bool _isDragged = false;
private static bool _refocused = true;
private static int _refocusedTaskIndex = 0;
private const int PANEL_MENUBAR_HEIGHT = 31;
private const uint TOUCH_FLAG = 0xFF515700;
@ -37,18 +36,30 @@ namespace MSFSPopoutPanelManager.WindowsAgent
public static void Hook()
{
// If using RSG GT750 Gen 1, disable touch support
if (ActiveProfile != null && ActiveProfile.RealSimGearGTN750Gen1Override)
return;
_simulatorProcess = WindowProcessManager.GetSimulatorProcess();
Process curProcess = Process.GetCurrentProcess();
ProcessModule curModule = curProcess.MainModule;
var hookWindowPtr = PInvoke.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
_hHook = PInvoke.SetWindowsHookEx(HookType.WH_MOUSE_LL, callbackDelegate, hookWindowPtr, 0);
}
public static void UnHook()
{
PInvoke.UnhookWindowsHookEx(_hHook);
_hHook = IntPtr.Zero;
// If using RSG GT750 Gen 1, disable touch support
if (ActiveProfile != null && ActiveProfile.RealSimGearGTN750Gen1Override)
return;
if (_hHook != IntPtr.Zero)
{
PInvoke.UnhookWindowsHookEx(_hHook);
_hHook = IntPtr.Zero;
}
}
public static bool IsHooked { get { return _hHook != IntPtr.Zero; } }
@ -58,7 +69,6 @@ namespace MSFSPopoutPanelManager.WindowsAgent
if (code != 0)
return PInvoke.CallNextHookEx(_hHook, code, wParam, lParam);
var info = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
var extraInfo = (uint)info.dwExtraInfo;
var isTouched = (extraInfo & TOUCH_FLAG) == TOUCH_FLAG;
@ -104,9 +114,7 @@ namespace MSFSPopoutPanelManager.WindowsAgent
case WM_LBUTTONDOWN:
if (!_isTouchDown)
{
_refocused = false;
_isTouchDown = true;
_isMouseMoveBlock = true;
lock (_mouseTouchLock)
{
@ -121,7 +129,6 @@ namespace MSFSPopoutPanelManager.WindowsAgent
Thread.Sleep(AppSetting.TouchScreenSettings.TouchDownUpDelay + 25);
PInvoke.mouse_event(MOUSEEVENTF_LEFTDOWN, info.pt.X, info.pt.Y, 0, 0);
Thread.Sleep(AppSetting.TouchScreenSettings.TouchDownUpDelay + 50);
_isMouseMoveBlock = false;
_isTouchDown = false;
});
}
@ -142,11 +149,25 @@ namespace MSFSPopoutPanelManager.WindowsAgent
_isDragged = false;
}
_mouseMoveCount = 0;
RefocusMsfsGameWindow(panelConfig);
// Refocus game window
if (AppSetting.TouchScreenSettings.RefocusGameWindow && !panelConfig.DisableGameRefocus)
{
_refocusedTaskIndex++;
var currentRefocusIndex = _refocusedTaskIndex;
Thread.Sleep(AppSetting.TouchScreenSettings.RefocusGameWindowDelay);
if (currentRefocusIndex == _refocusedTaskIndex)
{
var rectangle = WindowActionManager.GetWindowRect(panelConfig.PanelHandle);
PInvoke.SetCursorPos(rectangle.X - 5, rectangle.Y + 5);
}
}
});
return 1;
case WM_MOUSEMOVE:
if (_isMouseMoveBlock)
if (_isTouchDown)
return 1;
_mouseMoveCount++;
@ -156,19 +177,5 @@ namespace MSFSPopoutPanelManager.WindowsAgent
return PInvoke.CallNextHookEx(_hHook, code, wParam, lParam);
}
private static void RefocusMsfsGameWindow(PanelConfig panelConfig)
{
Thread.Sleep(AppSetting.TouchScreenSettings.RefocusGameWindowDelay);
if (!_refocused && !_isTouchDown && AppSetting.TouchScreenSettings.RefocusGameWindow && !panelConfig.DisableGameRefocus)
{
_refocused = true;
var rectangle = WindowActionManager.GetWindowRect(_simulatorProcess.Handle);
var clientRectangle = WindowActionManager.GetClientRect(_simulatorProcess.Handle);
PInvoke.SetCursorPos(rectangle.X + clientRectangle.Width / 2, rectangle.Y + clientRectangle.Height / 2);
}
}
}
}

View file

@ -262,17 +262,22 @@
<ScrollViewer VerticalScrollBarVisibility="Auto">
<WrapPanel Orientation="Vertical" Visibility="{Binding TouchSettingsVisible, Converter={StaticResource VisibleIfTrueConverter}, Mode=OneWay}">
<WrapPanel Orientation="Vertical" Margin="0,0,20,20">
<TextBlock Style="{StaticResource TextBlockHeading}">Refocus Game Window</TextBlock>
<Line Stretch="Fill" Stroke="Gray" X2="1"/>
<CheckBox IsChecked="{Binding AppSettingData.AppSetting.TouchScreenSettings.RefocusGameWindow, Mode=TwoWay}" >
<AccessText TextWrapping="Wrap">Automactically set focus back to game window after a period of inactivity on touch enabled panel. This will give your flight control back when using pop out panel.</AccessText>
</CheckBox>
<WrapPanel Margin="0,10,0,0">
<mah:NumericUpDown Width="100" Minimum="500" Maximum="2000" Interval="500" FontSize="16" Height="32" Value="{Binding AppSettingData.AppSetting.TouchScreenSettings.RefocusGameWindowDelay, Mode=TwoWay}"></mah:NumericUpDown>
<AccessText Margin="10,0,0,0" Width="490">Amount of time in milliseconds to wait for touch inactivity before input focus goes back to game window.</AccessText>
<WrapPanel Orientation="Vertical" Margin="0,0,20,20">
<TextBlock Style="{StaticResource TextBlockHeading}">Refocus Game Window</TextBlock>
<Line Stretch="Fill" Stroke="Gray" X2="1"/>
<CheckBox IsChecked="{Binding AppSettingData.AppSetting.TouchScreenSettings.RefocusGameWindow, Mode=TwoWay}" >
<AccessText TextWrapping="Wrap">Automactically set focus back to game window after a period of inactivity on touch enabled panel. This will give your flight control back when using pop out panel.</AccessText>
</CheckBox>
<WrapPanel Margin="0,10,0,0">
<mah:NumericUpDown Width="100" Minimum="500" Maximum="10000" Interval="500" FontSize="16" Height="32" Value="{Binding AppSettingData.AppSetting.TouchScreenSettings.RefocusGameWindowDelay, Mode=TwoWay}"></mah:NumericUpDown>
<AccessText Margin="10,0,0,0" Width="490">Amount of time in milliseconds to wait for touch inactivity before input focus goes back to game window.</AccessText>
</WrapPanel>
<WrapPanel Margin="0,10,0,0">
<CheckBox IsChecked="{Binding AppSettingData.AppSetting.TouchScreenSettings.RealSimGearGTN750Gen1Override, Mode=TwoWay}" >
<AccessText Margin="10,0,0,0" Width="490">Use custom refocus logic for RealSimGear GTN750 Gen1.</AccessText>
</CheckBox>
</WrapPanel>
</WrapPanel>
</WrapPanel>
<WrapPanel Orientation="Vertical" Margin="0,0,20,20">
<TextBlock Style="{StaticResource TextBlockHeading}">Touch Down Touch Up Delay</TextBlock>
<Line Stretch="Fill" Stroke="Gray" X2="1"/>

View file

@ -78,6 +78,9 @@
</WrapPanel>
<CheckBox Margin="10,5,0,0" Content="Power on required to pop out panels on cold start (G1000 / NXi Only)" IsChecked="{Binding ProfileData.ActiveProfile.PowerOnRequiredForColdStart}" Command="{Binding SetPowerOnRequiredCommand}" />
<CheckBox Margin="10,5,0,0" Content="Include in-game menu bar panels (VFR Map, Checklist, ATC, etc)" IsChecked="{Binding ProfileData.ActiveProfile.IncludeInGamePanels}" Command="{Binding SetIncludeInGamePanelsCommand}" />
<WrapPanel Orientation="Horizontal" Visibility="{Binding AppSettingData.AppSetting.TouchScreenSettings.RealSimGearGTN750Gen1Override, Converter={StaticResource VisibleIfTrueConverter}, Mode=OneWay}" >
<CheckBox Margin="10,5,0,0" Content="RealSimGear GTN750 Gen1" IsChecked="{Binding ProfileData.ActiveProfile.RealSimGearGTN750Gen1Override}" Command="{Binding SetIncludeInGamePanelsCommand}" />
</WrapPanel>
<WrapPanel Name="TouchPanelConfigurationPanel" Orientation="Horizontal" Margin="0,10,0,0" Visibility="{Binding AppSettingData.AppSetting.IsEnabledTouchPanelServer, Converter={StaticResource VisibleIfTrueConverter}, Mode=OneWay}" >
<Label Content="Open MSFS touch panel when flight session starts" Margin="5,0,0,0" />
<Button Content="+" ToolTip="Add Binding" Margin="94,0,0,0" Width="40" Command="{Binding OpenTouchPanelBindingCommand}"/>