Interface Connection

All Superinterfaces:
AutoCloseable
All Known Implementing Classes:
AbstractConnection

public interface Connection extends AutoCloseable
Represent a connection to either a local/direct/remote Terminal.
Author:
Ståle W. Pedersen
  • Method Details

    • device

      Device device()
      Get the device associated with this connection.
      Returns:
      type of terminal
    • size

      Size size()
      Get the current terminal size.
      Returns:
      terminal size
    • getSizeHandler

      Consumer<Size> getSizeHandler()
      Get the size handler.
      Returns:
      Handler that's called when the terminal changes size
    • setSizeHandler

      void setSizeHandler(Consumer<Size> handler)
      Specify size handler that's called when the terminal changes size.
      Parameters:
      handler - the size change handler
    • getSignalHandler

      Consumer<Signal> getSignalHandler()
      Get SignalHandler. A handler that's called when a Signal is sent to the terminal
      Returns:
      Signal handler
    • setSignalHandler

      void setSignalHandler(Consumer<Signal> handler)
      Specify the signal handler. A handler that's called when a Signal is sent to the terminal
      Parameters:
      handler - signal handler
    • getStdinHandler

      Consumer<int[]> getStdinHandler()
      Get the standard input handler.
      Returns:
      the stdin handler that processes input as code point arrays
    • setStdinHandler

      void setStdinHandler(Consumer<int[]> handler)
      Set the standard input handler.
      Parameters:
      handler - the handler to process input as code point arrays
    • stdoutHandler

      Consumer<int[]> stdoutHandler()
      Handler that's called for all output
      Returns:
      output handler
    • setCloseHandler

      void setCloseHandler(Consumer<Void> closeHandler)
      Specify handler that's called when the input stream is closed.
      Parameters:
      closeHandler - handler
    • getCloseHandler

      Consumer<Void> getCloseHandler()
      Get the close handler.
      Returns:
      handler thats called when the input stream is closed.
    • close

      void close()
      Stop reading from the input stream. The stream will be closed and cleanup methods will be called Eg for terminals they will be restored to their original settings. Note that if the reader thread is blocking waiting for data it will wait until either killed or if the input stream is closed.
      Specified by:
      close in interface AutoCloseable
    • close

      default void close(int exit)
      Close the connection with an exit code.
      Parameters:
      exit - the exit code
    • openBlocking

      void openBlocking()
      Start reading from the input stream using the current thread. The current thread will be blocked while reading/waiting to read from the stream
    • openNonBlocking

      void openNonBlocking()
      Start reading from the input stream in a separate thread. The current thread will continue.
    • reading

      default boolean reading()
      Check if the connection is actively reading from the input stream.

      This returns true after openBlocking() or openNonBlocking() has been called and before close() is called.

      When reading is active, query methods can use setStdinHandler(Consumer) to receive responses. When reading is not active, synchronous I/O must be used.

      Returns:
      true if the connection is actively reading input
    • put

      boolean put(Capability capability, Object... params)
      Specify terminal settings
      Parameters:
      capability - capability
      params - parameters
      Returns:
      true if the terminal accepted the settings
    • getAttributes

      Attributes getAttributes()
      Get the current terminal attributes.
      Returns:
      the terminal attributes
    • setAttributes

      void setAttributes(Attributes attr)
      Set the terminal attributes.
      Parameters:
      attr - the attributes to set
    • inputEncoding

      Charset inputEncoding()
      Get the input character encoding.
      Returns:
      the charset used for input encoding
    • outputEncoding

      Charset outputEncoding()
      Get the output character encoding.
      Returns:
      the charset used for output encoding
    • supportsAnsi

      boolean supportsAnsi()
      Check if this terminal supports ANSI escape sequences.
      Returns:
      true if ANSI is supported, false otherwise
    • write

      default Connection write(String s)
      Write a string to the output handler. When the stdout handler is an Encoder, this uses a fast path that encodes the String directly to bytes without an intermediate int[] allocation.
      Parameters:
      s - string
      Returns:
      this connection
    • enterRawMode

      default Attributes enterRawMode()
      Enter raw mode for the terminal.

      In raw mode, input is not line-buffered, echo is disabled, and special character processing is turned off. This allows reading individual keystrokes as they are typed.

      Returns:
      the previous terminal attributes (to restore later)
    • getCursorPosition

      default Point getCursorPosition()
      Get the current cursor position in the terminal.

      This method sends a cursor position query to the terminal and waits for the response. The terminal must be actively reading input for this to work.

      Returns:
      the current cursor position as a Point (row, column)
    • queryTerminal

      default <T> T queryTerminal(String query, long timeoutMs, Function<int[],T> responseParser)
      Send a query to the terminal and wait for a response with timeout.

      This method enters raw mode, sends the query, collects the response, and restores the original terminal attributes. It's useful for both OSC queries and CSI queries (DA1/DA2, DECRQM, theme DSR, etc.).

      This method uses setStdinHandler(Consumer) to receive responses, which requires the connection to be actively reading input (i.e., reading() returns true). If not reading, this method returns null.

      For queries that need to work before the connection is opened, use queryColorCapability(long) or implementation-specific synchronous methods.

      Type Parameters:
      T - the type of the parsed response
      Parameters:
      query - the query sequence to send
      timeoutMs - timeout in milliseconds to wait for response
      responseParser - function to parse the response; should return non-null when a complete response is received, null to continue waiting
      Returns:
      the parsed response, or null if not reading, timeout, or parsing failed
    • supportsOscQueries

      default boolean supportsOscQueries()
      Check if OSC (Operating System Command) queries are supported.

      This checks both the device type and environment variables to determine if OSC queries like color detection are likely to work. Uses TerminalEnvironment for centralized detection.

      For more accurate detection, use supportsOscQueries(DeviceAttributes) with DA1 query results.

      Returns:
      true if OSC queries are likely supported
    • supportsOscQueries

      default boolean supportsOscQueries(DeviceAttributes attrs)
      Check if OSC queries are supported, using DA1 device attributes for improved detection.

      This method uses the device attributes from a DA1 query to provide more accurate OSC support detection. If the terminal reports modern features like ANSI color or Sixel graphics, it likely supports OSC queries.

      Parameters:
      attrs - the device attributes from DA1 query (may be null)
      Returns:
      true if OSC queries are likely supported
    • querySupportsOscQueries

      default boolean querySupportsOscQueries(long timeoutMs)
      Query the terminal to check if OSC queries are supported.

      This method sends a DA1 query to get device attributes and uses them to determine OSC support more accurately than heuristic detection.

      Parameters:
      timeoutMs - timeout in milliseconds for the DA1 query
      Returns:
      true if OSC queries are likely supported
    • getColorDepth

      default ColorDepth getColorDepth()
      Get the color depth of this terminal connection.

      This method uses the device's max_colors capability if available, otherwise falls back to environment variable detection.

      Returns:
      the detected color depth
    • getColorCapability

      default TerminalColorCapability getColorCapability()
      Get the color capabilities of this terminal connection.

      This is a fast, non-blocking operation that uses environment variables and terminfo data. For more accurate color detection including background theme detection via OSC queries, use the TerminalColorDetector class in the readline module.

      Returns:
      the detected color capabilities
    • queryOsc

      default <T> T queryOsc(int oscCode, String param, long timeoutMs, Function<int[],T> responseParser)
      Send an OSC (Operating System Command) query to the terminal.

      This method sends an OSC query sequence and waits for the terminal's response. The terminal must be actively reading input (via openBlocking() or openNonBlocking()) for this to work.

      Common OSC codes:

      • 10 - Query/set foreground color
      • 11 - Query/set background color
      • 12 - Query/set cursor color
      • 4;N - Query/set palette color N
      Type Parameters:
      T - the type of the parsed response
      Parameters:
      oscCode - the OSC code (e.g., 10 for foreground, 11 for background)
      param - the query parameter (typically "?" for queries)
      timeoutMs - timeout in milliseconds to wait for response
      responseParser - function to parse the response; should return non-null when a complete response is received, null to continue waiting
      Returns:
      the parsed response, or null if timeout or not supported
    • queryForegroundColor

      default int[] queryForegroundColor(long timeoutMs)
      Query the terminal for its foreground color using OSC 10.

      The terminal must be actively reading input for this to work.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for response
      Returns:
      RGB array [r, g, b] (0-255 each), or null if not supported or timeout
    • queryBackgroundColor

      default int[] queryBackgroundColor(long timeoutMs)
      Query the terminal for its background color using OSC 11.

      The terminal must be actively reading input for this to work.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for response
      Returns:
      RGB array [r, g, b] (0-255 each), or null if not supported or timeout
    • queryCursorColor

      default int[] queryCursorColor(long timeoutMs)
      Query the terminal for its cursor color using OSC 12.

      The terminal must be actively reading input for this to work.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for response
      Returns:
      RGB array [r, g, b] (0-255 each), or null if not supported or timeout
    • queryThemeMode

      default TerminalTheme queryThemeMode(long timeoutMs)
      Query the terminal for its current theme mode using the CSI ? 996 n protocol.

      This sends CSI ? 996 n and expects a response of CSI ? 997 ; 1 n (dark) or CSI ? 997 ; 2 n (light).

      This is simpler and faster than OSC 10/11 RGB queries since it returns a direct dark/light answer without needing luminance calculation.

      The terminal must be actively reading input for this to work. Only works on terminals that support this extension (Contour, Ghostty, Kitty 0.38.1+, tmux, VTE 0.82.0+).

      Ref: Contour VT extension: Dark and Light Mode detection

      Parameters:
      timeoutMs - timeout in milliseconds to wait for response
      Returns:
      TerminalTheme.DARK or TerminalTheme.LIGHT, or null if not supported or timeout
    • supportsThemeQuery

      default boolean supportsThemeQuery()
      Check if the terminal supports the CSI ? 996 n theme mode query.

      Delegates to Device.supportsThemeQuery().

      Returns:
      true if the terminal supports theme mode queries
    • setThemeChangeHandler

      default void setThemeChangeHandler(Consumer<TerminalTheme> handler)
      Set a handler to be called when the terminal's theme changes.

      When a handler is registered, the input pipeline will intercept unsolicited CSI ? 997 ; Ps n responses and route them to this handler instead of passing them through as input. This prevents theme change notifications from corrupting the readline buffer.

      Typically used together with enableThemeChangeNotification() which tells the terminal to send these notifications.

      Note: The default implementation is a no-op. Implementations that extend AbstractConnection get automatic support via EventDecoder.

      Parameters:
      handler - the handler to invoke with the new theme, or null to remove
      See Also:
    • getThemeChangeHandler

      default Consumer<TerminalTheme> getThemeChangeHandler()
      Get the current theme change handler.
      Returns:
      the theme change handler, or null if not set
      See Also:
    • enableThemeChangeNotification

      default void enableThemeChangeNotification()
      Enable unsolicited theme change notifications.

      Sends CSI ? 2031 h to the terminal. When enabled, the terminal will send CSI ? 997 ; 1 n or CSI ? 997 ; 2 n whenever the color palette changes (e.g., dark/light mode switch).

      To receive these notifications, also register a handler with setThemeChangeHandler(Consumer).

      Use disableThemeChangeNotification() to stop receiving notifications.

      Ref: Contour VT extension

    • enableThemeChangeNotification

      default void enableThemeChangeNotification(Consumer<TerminalTheme> handler)
      Enable unsolicited theme change notifications with a handler.

      Convenience method that registers the theme change handler and enables notifications in one call. Equivalent to:

       connection.setThemeChangeHandler(handler);
       connection.enableThemeChangeNotification();
       

      The handler is called whenever the terminal reports a theme change. Applications can update their cached TerminalColorCapability in the handler:

       connection.enableThemeChangeNotification(theme -> {
           capability = new TerminalColorCapability(capability.getColorDepth(), theme);
       });
       
      Parameters:
      handler - the handler to invoke with the new theme
      See Also:
    • disableThemeChangeNotification

      default void disableThemeChangeNotification()
      Disable unsolicited theme change notifications.

      Sends CSI ? 2031 l to the terminal. Does not remove the theme change handler — call setThemeChangeHandler(Consumer) with null to remove it.

      See Also:
    • queryOsc

      default <T> T queryOsc(int oscCode, int index, String param, long timeoutMs, Function<int[],T> responseParser)
      Send an OSC query with an index parameter to the terminal.

      This is used for OSC codes that require an index, such as OSC 4 (palette colors).

      The terminal must be actively reading input for this to work.

      Type Parameters:
      T - the type of the parsed response
      Parameters:
      oscCode - the OSC code (e.g., 4 for palette color)
      index - the index parameter (e.g., palette color index 0-255)
      param - the query parameter (typically "?" for queries)
      timeoutMs - timeout in milliseconds to wait for response
      responseParser - function to parse the response; should return non-null when a complete response is received, null to continue waiting
      Returns:
      the parsed response, or null if timeout or not supported
    • queryPaletteColor

      default int[] queryPaletteColor(int index, long timeoutMs)
      Query the terminal for a palette color using OSC 4.

      Palette colors are indexed 0-255, where:

      • 0-7: Standard ANSI colors
      • 8-15: Bright ANSI colors
      • 16-231: 216-color cube
      • 232-255: Grayscale ramp

      The terminal must be actively reading input for this to work.

      Parameters:
      index - the palette color index (0-255)
      timeoutMs - timeout in milliseconds to wait for response
      Returns:
      RGB array [r, g, b] (0-255 each), or null if not supported or timeout
    • queryWithResponseBuffering

      default Map<Integer,int[]> queryWithResponseBuffering(long timeoutMs, int expectedCount, String batchQuery, Function<int[],Map<Integer,int[]>> parser)
      Shared orchestration for batch OSC queries with response buffering.

      This method handles the common pattern of saving the stdin handler, entering raw mode, buffering responses, parsing them, and restoring state.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for all responses
      expectedCount - the number of expected responses
      batchQuery - the concatenated query string to send
      parser - function to parse the buffered response into a result map
      Returns:
      map from key to RGB array [r, g, b] (0-255 each)
    • queryBatchOsc

      default Map<Integer,int[]> queryBatchOsc(long timeoutMs, int... oscCodes)
      Query multiple OSC color codes in a single batch operation.

      This method is much more efficient than calling individual query methods (like queryForegroundColor(long), queryBackgroundColor(long)) multiple times. By sending all queries at once and collecting responses in a single operation, latency is reduced from O(n * timeout) to O(timeout).

      For example, querying 10 colors individually might take 600-700ms due to serial round-trips, while batch querying takes only 50-100ms.

      The terminal must be actively reading input for this to work.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for all responses
      oscCodes - the OSC codes to query (e.g., 10 for foreground, 11 for background)
      Returns:
      map from OSC code to RGB array [r, g, b] (0-255 each); missing entries indicate the terminal didn't respond to that query
    • queryColors

      default Map<Integer,int[]> queryColors(long timeoutMs)
      Query foreground, background, and cursor colors in a single batch operation.

      This is a convenience method equivalent to calling queryBatchOsc(timeoutMs, 10, 11, 12).

      The returned map uses OSC codes as keys:

      The terminal must be actively reading input for this to work.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for all responses
      Returns:
      map from OSC code to RGB array [r, g, b] (0-255 each)
    • queryPaletteColors

      default Map<Integer,int[]> queryPaletteColors(long timeoutMs, int... indices)
      Query multiple palette colors in a single batch operation.

      This method sends all palette color queries at once, significantly reducing latency compared to calling queryPaletteColor(int, long) multiple times.

      The terminal must be actively reading input for this to work.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for all responses
      indices - the palette color indices to query (0-255)
      Returns:
      map from palette index to RGB array [r, g, b] (0-255 each); missing entries indicate the terminal didn't respond to that query
    • queryAnsi16Colors

      default Map<Integer,int[]> queryAnsi16Colors(long timeoutMs)
      Query the ANSI 16-color palette (colors 0-15) in a single batch operation.

      This queries the 8 standard colors (0-7) and 8 bright colors (8-15).

      The terminal must be actively reading input for this to work.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for all responses
      Returns:
      map from palette index (0-15) to RGB array [r, g, b] (0-255 each)
    • queryPrimaryDeviceAttributes

      default DeviceAttributes queryPrimaryDeviceAttributes(long timeoutMs)
      Query the terminal for its primary device attributes (DA1).

      DA1 returns the device conformance level and supported features. This can be used to detect capabilities like:

      • Sixel graphics support
      • ANSI color support
      • Mouse/locator support
      • Rectangular editing operations

      The terminal must be actively reading input for this to work.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for response
      Returns:
      DeviceAttributes with DA1 data, or null if not supported or timeout
    • querySecondaryDeviceAttributes

      default DeviceAttributes querySecondaryDeviceAttributes(long timeoutMs)
      Query the terminal for its secondary device attributes (DA2).

      DA2 returns terminal identification information:

      • Terminal type (VT100, VT220, xterm, etc.)
      • Firmware/version number
      • ROM cartridge registration

      Note: Not all terminals support DA2. Some may return nothing or the same response as DA1.

      The terminal must be actively reading input for this to work.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for response
      Returns:
      DeviceAttributes with DA2 data, or null if not supported or timeout
    • queryDeviceAttributes

      default DeviceAttributes queryDeviceAttributes(long timeoutMs)
      Query the terminal for both primary and secondary device attributes.

      This sends both DA1 and DA2 queries and merges the results into a single DeviceAttributes object containing all available information.

      The terminal must be actively reading input for this to work.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for each response
      Returns:
      DeviceAttributes with merged DA1 and DA2 data, or null if neither succeeded
    • queryImageProtocol

      default ImageProtocol queryImageProtocol(long timeoutMs)
      Query the terminal for its image protocol support.

      This method sends a DA1 query to detect Sixel support authoritatively, and combines it with heuristic detection based on terminal type.

      For faster (but less accurate) detection without querying the terminal, use Device.getImageProtocol() instead.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for DA1 response
      Returns:
      the detected image protocol
    • supportsSynchronizedOutput

      default boolean supportsSynchronizedOutput()
      Check if Mode 2026 (synchronized output) is likely supported.

      This delegates to the device's capability detection based on terminal type. Returns false for dumb terminals or when the device is null.

      Returns:
      true if Mode 2026 is likely supported
    • querySynchronizedOutput

      default Boolean querySynchronizedOutput(long timeoutMs)
      Query the terminal to check if Mode 2026 is supported via DECRQM.

      This sends a DECRQM (DEC Private Mode Request Mode) query for Mode 2026 and parses the DECRPM response.

      The terminal must be actively reading input for this to work.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for response
      Returns:
      true if supported, false if not supported, null if no response/timeout
    • enableSynchronizedOutput

      default Connection enableSynchronizedOutput()
      Enable Mode 2026 (synchronized output) — Begin Synchronized Update (BSU).

      When enabled, the terminal buffers rendering until the mode is disabled, then paints the final state in one frame.

      Returns:
      this connection
    • disableSynchronizedOutput

      default Connection disableSynchronizedOutput()
      Disable Mode 2026 (synchronized output) — End Synchronized Update (ESU).

      When disabled, the terminal renders the buffered output in a single frame.

      Returns:
      this connection
    • supportsShellIntegration

      default boolean supportsShellIntegration()
      Check if OSC 133 (shell integration) is likely supported.

      This delegates to the device's capability detection based on terminal type. Returns false for dumb terminals or when the device is null.

      Returns:
      true if OSC 133 shell integration is likely supported
    • writePromptStart

      default Connection writePromptStart()
      Write OSC 133;A (Prompt Start) to the terminal.

      This marks the beginning of the prompt region. Terminals that support shell integration use this to identify prompt boundaries for features like click-to-scroll-to-prompt and visual prompt highlighting.

      Returns:
      this connection
    • writePromptEnd

      default Connection writePromptEnd()
      Write OSC 133;B (Prompt End) to the terminal.

      This marks the end of the prompt and the start of the user input area.

      Returns:
      this connection
    • writeCommandStart

      default Connection writeCommandStart()
      Write OSC 133;C (Command Start) to the terminal.

      This marks that the user has pressed Enter and command output is about to begin.

      Returns:
      this connection
    • writeCommandFinished

      default Connection writeCommandFinished()
      Write OSC 133;D (Command Finished) to the terminal without an exit code.
      Returns:
      this connection
    • writeCommandFinished

      default Connection writeCommandFinished(int exitCode)
      Write OSC 133;D (Command Finished) to the terminal with an exit code.

      The exit code allows the terminal to visually distinguish successful commands (exit code 0) from failed commands.

      Parameters:
      exitCode - the command exit code
      Returns:
      this connection
    • supportsGraphemeClusterMode

      default boolean supportsGraphemeClusterMode()
      Check if Mode 2027 (grapheme cluster segmentation) is likely supported.

      This delegates to the device's capability detection based on terminal type. Returns false for dumb terminals or when the device is null.

      Returns:
      true if Mode 2027 is likely supported
    • queryGraphemeClusterMode

      default Boolean queryGraphemeClusterMode(long timeoutMs)
      Query the terminal to check if Mode 2027 is supported via DECRQM.

      This sends a DECRQM (DEC Private Mode Request Mode) query for Mode 2027 and parses the DECRPM response.

      The terminal must be actively reading input for this to work.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for response
      Returns:
      true if supported, false if not supported, null if no response/timeout
    • enableGraphemeClusterMode

      default Connection enableGraphemeClusterMode()
      Enable Mode 2027 (grapheme cluster segmentation).

      When enabled, the terminal uses UAX #29 grapheme cluster segmentation for cursor positioning instead of per-codepoint wcwidth.

      Returns:
      this connection
    • disableGraphemeClusterMode

      default Connection disableGraphemeClusterMode()
      Disable Mode 2027 (grapheme cluster segmentation).

      When disabled, the terminal reverts to per-codepoint wcwidth for cursor positioning.

      Returns:
      this connection
    • supportsHyperlinks

      default boolean supportsHyperlinks()
      Check if OSC 8 hyperlinks are likely supported.
      Returns:
      true if OSC 8 hyperlinks are likely supported
    • writeHyperlink

      default Connection writeHyperlink(String url, String text)
      Write a clickable hyperlink to the terminal.
      Parameters:
      url - the hyperlink URL
      text - the visible text
      Returns:
      this connection
    • writeHyperlink

      default Connection writeHyperlink(String url, String text, String id)
      Write a clickable hyperlink with a grouping id.
      Parameters:
      url - the hyperlink URL
      text - the visible text
      id - the grouping id
      Returns:
      this connection
    • getTerminalType

      default Device.TerminalType getTerminalType()
      Get the detected terminal type based on environment variables.

      This can be used to check OSC support before querying.

      Returns:
      the detected terminal type
    • supportsOscCode

      default boolean supportsOscCode(Device.OscCode oscCode)
      Check if the terminal likely supports a specific OSC code.
      Parameters:
      oscCode - the OSC code to check
      Returns:
      true if the terminal likely supports this OSC code
    • supportsPaletteQuery

      default boolean supportsPaletteQuery()
      Check if the terminal likely supports OSC 4 palette color queries.

      Some terminals (e.g., JetBrains IDEs) don't support OSC 4. Use this method to avoid unnecessary timeout waits.

      Returns:
      true if OSC 4 is likely supported
    • supportsColorQuery

      default boolean supportsColorQuery()
      Check if the terminal likely supports OSC 10/11 color queries.
      Returns:
      true if OSC 10/11 are likely supported
    • supportsClipboard

      default boolean supportsClipboard()
      Check if the terminal likely supports OSC 52 clipboard access.
      Returns:
      true if OSC 52 clipboard access is likely supported
    • queryPaletteColorIfSupported

      default int[] queryPaletteColorIfSupported(int index, long timeoutMs)
      Query palette color only if the terminal supports it.

      This method first checks if the terminal is known to support OSC 4, avoiding unnecessary timeout waits on unsupported terminals.

      Parameters:
      index - the palette color index (0-255)
      timeoutMs - timeout in milliseconds to wait for response
      Returns:
      RGB array [r, g, b] (0-255 each), or null if not supported or timeout
    • queryColorCapability

      default TerminalColorCapability queryColorCapability(long timeoutMs)
      Query terminal color capabilities using synchronous I/O.

      This method queries the terminal for color information including:

      • Foreground color (OSC 10)
      • Background color (OSC 11)
      • Cursor color (OSC 12, if supported)
      • Palette colors (OSC 4, if supported)

      Unlike queryTerminal(String, long, java.util.function.Function) and other handler-based query methods, this method uses synchronous I/O and works regardless of reading() state. It can be called before openBlocking() or openNonBlocking().

      The default implementation returns null. Implementations that support synchronous queries (like TerminalConnection) should override this method.

      Parameters:
      timeoutMs - timeout in milliseconds to wait for all responses
      Returns:
      TerminalColorCapability with detected colors, or null if not supported