diff --git a/source/Reloaded.Mod.Launcher/Pages/BasePage.xaml.cs b/source/Reloaded.Mod.Launcher/Pages/BasePage.xaml.cs index 2d42f081..959ff725 100644 --- a/source/Reloaded.Mod.Launcher/Pages/BasePage.xaml.cs +++ b/source/Reloaded.Mod.Launcher/Pages/BasePage.xaml.cs @@ -26,7 +26,7 @@ private void OnLoaded(object sender, RoutedEventArgs e) { _owner = Window.GetWindow(this); _owner!.KeyDown += TrySwitchPage; - ControllerSupport.OnProcessCustomInputs += ProcessCustomInputs; + ControllerSupport.SubscribeCustomInputs(ProcessCustomInputs); } ~BasePage() => Dispose(); @@ -34,7 +34,7 @@ private void OnLoaded(object sender, RoutedEventArgs e) public void Dispose() { _owner!.KeyDown -= TrySwitchPage; - ControllerSupport.OnProcessCustomInputs -= ProcessCustomInputs; + ControllerSupport.UnsubscribeCustomInputs(ProcessCustomInputs); GC.SuppressFinalize(this); } @@ -71,7 +71,7 @@ private void Application_Click(object sender, RoutedEventArgs e) ViewModel.SwitchToApplication(tuple); } - private void ProcessCustomInputs(in ControllerState state) + private void ProcessCustomInputs(in ControllerState state, ref bool handled) { if (!Window.GetWindow(this)!.IsActive) return; diff --git a/source/Reloaded.Mod.Launcher/Pages/BaseSubpages/ApplicationSubPages/AppSummaryPage.xaml.cs b/source/Reloaded.Mod.Launcher/Pages/BaseSubpages/ApplicationSubPages/AppSummaryPage.xaml.cs index fc293b42..ab173bd4 100644 --- a/source/Reloaded.Mod.Launcher/Pages/BaseSubpages/ApplicationSubPages/AppSummaryPage.xaml.cs +++ b/source/Reloaded.Mod.Launcher/Pages/BaseSubpages/ApplicationSubPages/AppSummaryPage.xaml.cs @@ -16,7 +16,7 @@ public AppSummaryPage() InitializeComponent(); ViewModel = Lib.IoC.Get(); - ControllerSupport.OnProcessCustomInputs += OnProcessCustomInputs; + ControllerSupport.SubscribeCustomInputs(OnProcessCustomInputs); _manipulator = new DictionaryResourceManipulator(this.Contents.Resources); _modsViewSource = _manipulator.Get("FilteredMods"); _modsViewSource.Filter += ModsViewSourceOnFilter; @@ -27,7 +27,7 @@ public AppSummaryPage() public void Dispose() { - ControllerSupport.OnProcessCustomInputs -= OnProcessCustomInputs; + ControllerSupport.UnsubscribeCustomInputs(OnProcessCustomInputs); ViewModel?.Dispose(); GC.SuppressFinalize(this); } @@ -75,7 +75,7 @@ private static void ProcessKeyboardItemShift(object sender, KeyEventArgs e) #region Controller Controls - private void OnProcessCustomInputs(in ControllerState state) + private void OnProcessCustomInputs(in ControllerState state, ref bool handled) { if (!WpfUtilities.TryGetFocusedElementAndWindow(out var window, out var focused)) return; diff --git a/source/Reloaded.Mod.Launcher/Utility/ControllerSupport.cs b/source/Reloaded.Mod.Launcher/Utility/ControllerSupport.cs index 620e8329..d27b23be 100644 --- a/source/Reloaded.Mod.Launcher/Utility/ControllerSupport.cs +++ b/source/Reloaded.Mod.Launcher/Utility/ControllerSupport.cs @@ -12,7 +12,8 @@ public static class ControllerSupport public static Navigator Navigator { get; private set; } = null!; - public static event ProcessCustomInputsDelegate OnProcessCustomInputs = (in ControllerState state) => { }; + private static List _processCustomInputsPreview = new(); + private static List _processCustomInputs = new(); public static void Init() { @@ -33,6 +34,12 @@ public static void Init() }); } + // Subscriptions for events handling custom preview. + public static void SubscribePreviewCustomInputs(ProcessCustomInputsRoutedDelegate processEvents) => _processCustomInputsPreview.Add(processEvents); + public static void UnsubscribePreviewCustomInputs(ProcessCustomInputsRoutedDelegate processEvents) => _processCustomInputsPreview.Remove(processEvents); + public static void SubscribeCustomInputs(ProcessCustomInputsRoutedDelegate processEvents) => _processCustomInputs.Add(processEvents); + public static void UnsubscribeCustomInputs(ProcessCustomInputsRoutedDelegate processEvents) => _processCustomInputs.Remove(processEvents); + /// /// Tries to get the page scroll direction based on input. /// @@ -78,7 +85,22 @@ internal static bool TryGetListScrollDirection(ControllerState state, out int di private static void ProcessCustomInputs(in ControllerState state) { ProcessCustomControls(state); - OnProcessCustomInputs(state); + + // Send out preview event. + bool isHandled = false; + foreach (var previewEvent in _processCustomInputsPreview) + { + previewEvent(state, ref isHandled); + if (isHandled) + return; + } + + foreach (var bubbleUpEvent in _processCustomInputs) + { + bubbleUpEvent(state, ref isHandled); + if (isHandled) + return; + } } private static void ProcessCustomControls(in ControllerState state) @@ -136,4 +158,8 @@ private static void HandleNumeric(ControllerState state, NumericUpDown nud) if (state.IsButtonPressed(Decrement) || (state.IsButtonHeld(Modifier) && state.IsButtonPressed(Up | Left))) DecrementValue(); } + + /// The current state of the controller. + /// Whether the event has been handled. If handled state is signaled, no further events will be called. + public delegate void ProcessCustomInputsRoutedDelegate(in ControllerState state, ref bool handled); } \ No newline at end of file