One last change:
Your version used points_to_pixels() to get the cursor position.  This has problems with variable width fonts.  The new version sets the text to self.txt[:_cursor_pos], gets the width of that, then fills in the full text.