class_docstr: Utility to keep track of which handles are connectod to which callbacks.
  
  `add_win32_handle` starts a tiny event loop in another thread which waits
  for the Win32 handle to become ready. When this happens, the callback will
  be called in the current asyncio event loop using `call_soon_threadsafe`.
  
  `remove_win32_handle` will stop this tiny event loop.
  
  NOTE: We use this technique, so that we don't have to use the
        `ProactorEventLoop` on Windows and we can wait for things like stdin
        in a `SelectorEventLoop`. This is important, because our inputhook
        mechanism (used by IPython), only works with the `SelectorEventLoop`.
docstr: Add a Win32 handle to the event loop.
docstr_tok: ["Add","a","Win32","handle","to","the","event","loop","."]
code: def add_win32_handle(
      self, handle: HANDLE, callback: Callable[[], None]
  ) -> None:
      """
      Add a Win32 handle to the event loop.
      """
      handle_value = handle.value
  
      if handle_value is None:
          raise ValueError("Invalid handle.")
  
      # Make sure to remove a previous registered handler first.
      self.remove_win32_handle(handle)
  
      loop = get_running_loop()
      self._handle_callbacks[handle_value] = callback
  
      # Create remove event.
      remove_event = create_win32_event()
      self._remove_events[handle_value] = remove_event
  
      # Add reader.
      def ready() -> None:
          # Tell the callback that input's ready.
          try:
              callback()
          finally:
              run_in_executor_with_context(wait, loop=loop)
  
      # Wait for the input to become ready.
      # (Use an executor for this, the Windows asyncio event loop doesn't
      # allow us to wait for handles like stdin.)
      def wait() -> None:
          # Wait until either the handle becomes ready, or the remove event
          # has been set.
          result = wait_for_handles([remove_event, handle])
  
          if result is remove_event:
              windll.kernel32.CloseHandle(remove_event)
              return
          else:
              loop.call_soon_threadsafe(ready)
  
      run_in_executor_with_context(wait, loop=loop)
  
imports: from __future__ import annotations
  import os
  import sys
  from abc import abstractmethod
  from asyncio import get_running_loop
  from contextlib import contextmanager
  from ..utils import SPHINX_AUTODOC_RUNNING
  from ctypes import Array, pointer
  from ctypes.wintypes import DWORD, HANDLE
  from typing import Callable, ContextManager, Iterable, Iterator, TextIO
  from prompt_toolkit.eventloop import run_in_executor_with_context
  from prompt_toolkit.eventloop.win32 import create_win32_event, wait_for_handles
  from prompt_toolkit.key_binding.key_processor import KeyPress
  from prompt_toolkit.keys import Keys
  from prompt_toolkit.mouse_events import MouseButton, MouseEventType
  from prompt_toolkit.win32_types import INPUT_RECORD, KEY_EVENT_RECORD, MOUSE_EVENT_RECORD, STD_INPUT_HANDLE, EventTypes
  from .ansi_escape_sequences import REVERSE_ANSI_SEQUENCES
  from .base import Input
label_desc: Use image node_id 2 for calling the _Win32Handles obj's underlying member method code with example usage: obj.add_win32_handle(handle, callback) without return types