#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));
}
}