There are subtle issues with mouse-click cursor positioning which I try to get fixed.
The first patch makes sure that the cursor falls on the correct side of a character when clicked left of right from its center.
The second patch makes sure that when we click left or right of text, the cursor ends up at the beginning or end of the text.
Separately, they work fine. When combined, they lead to an erratic jump-back of the cursor after it had been already placed.
Here is a reproducer:
- run the combined code below
- open some text buffer and click into the text in different places
- observe where exactly the cursor bar ends up with relation to the positon of the mouse click
At some positions, the cursor bar is briefly visible in the correct position, and then jumps back one step. This is the position it would have ended up with out the fix in
The question is how to make the cursor end up in the right position always.
Here is the combined code:
(setq-default cursor-type 'bar) (defun posn-set-point (position) "Move point to POSITION. Select the corresponding window as well." (if (not (windowp (posn-window position))) (error "Position not in text area of window")) (select-window (posn-window position)) (let ((pos (posn-point position))) (if (numberp pos) (goto-char (if (and (eq 'bar (or (car-safe cursor-type) cursor-type)) (< pos (point-max)) (consp position) (numberp (car-safe (posn-object-x-y position))) (numberp (car-safe (posn-object-width-height position))) (> (* 2 (car (posn-object-x-y position))) (car (posn-object-width-height position)))) (1+ pos) pos))))) (defun mouse-goto-bol (click) "Move to beginning of line for mouse-1 click in left fringe." (interactive "e") (mouse-goto-line click 'left)) (defun mouse-goto-eol (click) "Move to beginning of line for mouse-1 click in left fringe." (interactive "e") (mouse-goto-line click 'right)) (defun mouse-goto-line (click left/right) "Helper for `mouse-goto-(bol|eol)'." (let* ((posn (event-start click)) (click-pt (posn-point posn)) (window (posn-window posn)) (buf (window-buffer window)) (clicks (if (eq mouse-selection-click-count-buffer buf) (event-click-count click) 0))) (when (= clicks 1) ; No-op if not single-click. (with-current-buffer buf (goto-char click-pt) (if (eq 'left left/right) (line-beginning-position) (line-end-position)))))) (global-set-key [left-fringe mouse-1] 'mouse-goto-bol) ;;(global-set-key [right-fringe mouse-1] 'mouse-goto-eol) (global-set-key (kbd "<mouse-1>") 'mouse-goto-eol)
The solutions are from: