public IObservable <InputAction.CallbackContext> PerformedAsObservable(int priority = 0)
    {
        void OnRemoveSubscriber(Action <InputAction.CallbackContext> onNext)
        {
            InputActionSubscriber subscriber = performedSubscribers
                                               .FirstOrDefault(it => it.Priority == priority && it.OnNext == onNext);

            performedSubscribers.Remove(subscriber);

            // No subscriber left in event queue. Thus, remove the callback from the InputAction.
            if (performedSubscribers.Count == 0)
            {
                InputAction.performed -= NotifyPerformedSubscribers;
                performedSubscribers   = null;
            }
        }

        void OnAddSubscriber(Action <InputAction.CallbackContext> onNext)
        {
            // Add the one callback that will update all subscribers
            if (performedSubscribers == null)
            {
                performedSubscribers   = new List <InputActionSubscriber>();
                InputAction.performed += NotifyPerformedSubscribers;
                Owner.OnDestroyAsObservable().Subscribe(_ => InputAction.performed -= NotifyPerformedSubscribers);
            }

            performedSubscribers.Add(new InputActionSubscriber(priority, onNext));
            performedSubscribers.Sort(CompareByPriority);
        }

        return(Observable.FromEvent <InputAction.CallbackContext>(OnAddSubscriber, OnRemoveSubscriber));
    }
 private void NotifyCanceledSubscribers(InputAction.CallbackContext callbackContext)
 {
     // Iteration over index to enable removing subscribers as part of the callback (i.e., during iteration).
     for (int i = 0; canceledSubscribers != null && i < canceledSubscribers.Count; i++)
     {
         if (notifyCancelledInFrame != Time.frameCount)
         {
             InputActionSubscriber subscriber = canceledSubscribers[i];
             subscriber.OnNext.Invoke(callbackContext);
         }
         else
         {
             return;
         }
     }
 }
 private int CompareByPriority(InputActionSubscriber a, InputActionSubscriber b)
 {
     // Sort descending: compare b to a
     return(b.Priority.CompareTo(a.Priority));
 }