After some debugging work, I think I find the cause.
When the input method is active, every char inputting triggers two events to emacs.
The first one is ‘(ns-unput-working-text), which will finally executes the lisp command ns-unput-working-text, which clears the current working text in buffer.
The second is ‘(ns-put-working-text), which will finally excutes the lisp command ns-put-working-text, which insert the new working text into the buffer.
PS: The working text is the tip chars of the input method. It is not the finally input content. It is the intermediate content of the user input.
The above two operations cause the flicker.
The resolution:
Don’t redisplay on the first event. Is it possible to disable redisplay for a command?
A workaround:
Because ns-put-working-text can also clear the old working text. So in ns-unput-working-text, we can clear the working text only when really needed and give the other work to ns-put-working-text.
I modified the ns-unput-working-text. And it works.
(defun ns-unput-working-text ()
(interactive)
(cond
((and (overlayp ns-working-overlay)
;; Still alive?
(overlay-buffer ns-working-overlay))
(with-current-buffer (overlay-buffer ns-working-overlay)
(let ((text (buffer-substring-no-properties
(overlay-start ns-working-overlay)
(overlay-end ns-working-overlay))))
(when (equal text ns-working-text)
(delete-region (overlay-start ns-working-overlay)
(overlay-end ns-working-overlay))
(delete-overlay ns-working-overlay)
(setq ns-working-overlay nil)))))
((integerp ns-working-overlay)
(let* ((msg (current-message))
(text (substring msg (- (length msg) ns-working-overlay)))
message-log-max)
(when (equal text ns-working-text)
(setq msg (substring msg 0 (- (length msg) ns-working-overlay)))
(message “%s” msg)
(setq ns-working-overlay nil))))))