#nullable enable namespace Terminal.Gui.App; /// /// INTERNAL: Implements to manage which (if any) has 'grabbed' the mouse, /// giving it exclusive priority for mouse events such as movement, button presses, and release. /// /// Used for scenarios like dragging, scrolling, or any interaction where a view needs to receive all mouse events /// until the operation completes (e.g., a scrollbar thumb being dragged). /// /// /// See for usage details. /// /// internal class MouseGrabHandler : IMouseGrabHandler { /// public View? MouseGrabView { get; private set; } /// public event EventHandler? GrabbingMouse; /// public event EventHandler? UnGrabbingMouse; /// public event EventHandler? GrabbedMouse; /// public event EventHandler? UnGrabbedMouse; /// public void GrabMouse (View? view) { if (view is null || RaiseGrabbingMouseEvent (view)) { return; } RaiseGrabbedMouseEvent (view); // MouseGrabView is a static; only set if the application is initialized. MouseGrabView = view; } /// public void UngrabMouse () { if (MouseGrabView is null) { return; } #if DEBUG_IDISPOSABLE if (View.EnableDebugIDisposableAsserts) { ObjectDisposedException.ThrowIf (MouseGrabView.WasDisposed, MouseGrabView); } #endif if (!RaiseUnGrabbingMouseEvent (MouseGrabView)) { View view = MouseGrabView; MouseGrabView = null; RaiseUnGrabbedMouseEvent (view); } } /// A delegate callback throws an exception. private bool RaiseGrabbingMouseEvent (View? view) { if (view is null) { return false; } var evArgs = new GrabMouseEventArgs (view); GrabbingMouse?.Invoke (view, evArgs); return evArgs.Cancel; } /// A delegate callback throws an exception. private bool RaiseUnGrabbingMouseEvent (View? view) { if (view is null) { return false; } var evArgs = new GrabMouseEventArgs (view); UnGrabbingMouse?.Invoke (view, evArgs); return evArgs.Cancel; } /// A delegate callback throws an exception. private void RaiseGrabbedMouseEvent (View? view) { if (view is null) { return; } GrabbedMouse?.Invoke (view, new (view)); } /// A delegate callback throws an exception. private void RaiseUnGrabbedMouseEvent (View? view) { if (view is null) { return; } UnGrabbedMouse?.Invoke (view, new (view)); } }