@NotNull
  VisualPosition xyToVisualPosition(@NotNull Point2D p) {
    int visualLine = yToVisualLine((int)p.getY());
    int lastColumn = 0;
    float x = getStartX(visualLine);
    float px = (float)p.getX();
    int logicalLine = -1;
    if (visualLine < myView.getEditor().getVisibleLineCount()) {
      int visualLineStartOffset = visualLineToOffset(visualLine);
      int maxOffset = 0;
      for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, visualLineStartOffset, false, true)) {
        if (fragment.getCurrentFoldRegion() instanceof CustomFoldRegion) {
          return new VisualPosition(visualLine, 0);
        }
        if (px <= fragment.getStartX()) {
          if (fragment.getStartVisualColumn() == 0) {
            return new VisualPosition(visualLine, 0);
          }
          int markerWidth = myView.getEditor().getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
          float indent = fragment.getStartX() - markerWidth;
          if (px <= indent) {
            break;
          }
          boolean after = px >= indent + markerWidth / 2;
          return new VisualPosition(visualLine, fragment.getStartVisualColumn() - (after ? 0 : 1), !after);
        }
        float nextX = fragment.getEndX();
        if (px <= nextX) {
          int[] column = fragment.xToVisualColumn(px);
          return new VisualPosition(visualLine, column[0], column[1] > 0);
        }
        x = nextX;
        lastColumn = fragment.getEndVisualColumn();
        maxOffset = Math.max(maxOffset, fragment.getMaxOffset());
        logicalLine = fragment.getEndLogicalLine();
      }
      if (myView.getEditor().getSoftWrapModel().getSoftWrap(maxOffset) != null) {
        int markerWidth = myView.getEditor().getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
        if (px <= x + markerWidth) {
          boolean after = px >= x + markerWidth / 2;
          return new VisualPosition(visualLine, lastColumn + (after ? 1 : 0), !after);
        }
        px -= markerWidth;
        lastColumn++;
        logicalLine = -1;
      }
      else if (logicalLine == -1) {
        logicalLine = myDocument.getLineNumber(visualLineStartOffset);
      }
    }
    float plainSpaceWidth = myView.getPlainSpaceWidth();
    float remainingShift = px - x;
    if (remainingShift > plainSpaceWidth && logicalLine >= 0) {
      List<Inlay<?>> inlays = myView.getEditor().getInlayModel().getAfterLineEndElementsForLogicalLine(logicalLine);
      int inlaysWidth = 0;
      int inlayCount = 0;
      for (Inlay inlay : inlays) {
        int width = inlay.getWidthInPixels();
        int newWidth = inlaysWidth + width;
        if (remainingShift <= plainSpaceWidth + newWidth) {
          boolean leftPart = remainingShift <= plainSpaceWidth + (inlaysWidth + newWidth) / 2;
          return new VisualPosition(visualLine, lastColumn + 1 + inlayCount + (leftPart ? 0 : 1), leftPart);
        }
        inlaysWidth = newWidth;
        inlayCount++;
      }
      remainingShift -= inlaysWidth;
      lastColumn += inlayCount;
    }
    int additionalColumns = remainingShift <= 0 ? 0 : Math.round(remainingShift / plainSpaceWidth);
    return new VisualPosition(visualLine, lastColumn + additionalColumns, remainingShift > additionalColumns * plainSpaceWidth);
  }
@NotNull
  VisualPosition xyToVisualPosition(@NotNull Point2D p)