@Override
  public void inputMethodTextChanged(InputMethodEvent event) {
    CefLog.Debug("InputMethodListener::inputMethodTextChanged(event: %s)", event);

    int committedCharacterCount = event.getCommittedCharacterCount();

    AttributedCharacterIterator text = event.getText();
    if (text == null) {
      return;
    }
    char c = text.first();
    if (committedCharacterCount > 0) {
      StringBuilder textBuffer = new StringBuilder();
      while (committedCharacterCount-- > 0) {
        textBuffer.append(c);
        c = text.next();
      }

      String committedText = textBuffer.toString();
      CefRange replacementRange = DEFAULT_RANGE;
      int relativeCursorPos = 0;
      CefLog.Debug("CefBrowser::ImeCommitText(compositionText: '%s', replacementRange: %s, selectionRange: %s)", committedText,
                   replacementRange, relativeCursorPos);
      myBrowser.ImeCommitText(committedText, replacementRange, relativeCursorPos);

      // CEF doesn't notify about changing the selection range after committing. Current data is outdated. The selection range is unknown.
      mySelectedText = "";
      mySelectionRange = DEFAULT_RANGE;
    }

    StringBuilder textBuffer = new StringBuilder();
    while (c != CharacterIterator.DONE) {
      textBuffer.append(c);
      c = text.next();
    }

    var composedText = textBuffer.toString();
    if (!composedText.isEmpty()) {
      Color color = new JBColor(new Color(0, true), new Color(0, true));
      CefCompositionUnderline underline =
        new CefCompositionUnderline(new CefRange(0, composedText.length()), color, color, 0, CefCompositionUnderline.Style.SOLID);

      CefRange replacementRange = mySelectionRange;
      if (replacementRange.from == replacementRange.to) {
        // It has been experimentally determined that replacementRange must have an actual value only if there is a text to be replaced.
        // Passing zero-length ranges pointing to the caret position breaks Korean Language input character order.
        replacementRange = DEFAULT_RANGE;
      }

      // Selection range after replacement. Move the caret at the end of the composed text.
      CefRange selectionRange = new CefRange(composedText.length(), composedText.length());
      CefLog.Debug("CefBrowser::ImeSetComposition(compositionText: '%s', replacementRange: %s, selectionRange: %s)", composedText,
                   replacementRange, selectionRange);
      myBrowser.ImeSetComposition(composedText, List.of(underline), replacementRange, selectionRange);
    }
    event.consume();
  }
@Override
  public void inputMethodTextChanged(InputMethodEvent event)