In a comment underneath the question, the O.P. stated that he/she is using a version of Emacs on macOS Catalina -- presumably the GUI version (although not stated one way or the other).
In the event that Alan Third (the maintainer of the macOS port of Emacs) reads this, I really do appreciate everything that he has done and continues to do to keep the macOS port of Emacs alive. My comments are not meant to be a criticism of anything he has implemented as a means of working around certain problems introduced by Apple ...
For at least as long as I have been using Emacs (i.e., version 24), and probably a lot longer than that, Emacs updated the glass directly during its redisplay cycle when running update_window
in dispnew.c
. All was well until Apple introduced its Mojave version of the macOS operating system -- effectively doing away with the ability for applications such as Emacs to update the glass directly at any given time during its redisplay cycle. In a nutshell, applications must now wait until the OS calls drawRect
to update the glass. It is possible (but not recommended), or at least it was possible the last time I checked, to force the OS to call drawRect
out of order in its normal redisplay cycle.
As of 09/28/2018 (7946445962372c4255180af45cb7c857f1b0b5fa), the macOS port of Emacs now only marks dirty rectangles (areas that need updating) during update_window
and then Emacs has to wait until the OS calls drawRect
to update the areas of the glass that had been marked as dirty -- triggering Emacs to run expose_frame
on said areas. That changeover in the way the glass is updated during redisplay causes certain screen glitches (e.g., flickering) in terms of areas that do not update correctly and/or certain additional areas of the screen are redrawn (which was not the case prior to 09/28/2018). I do not have a solution for those issues, sorry.
I would suggest that the O.P. reduce the number of calls to recenter
to an absolute bare minimum. My preference would be to run recenter
prior to isearch
calling isearch-update
, because the latter updates the display based upon the lay of the land. I.e., running recenter
after isearch
runs isearch-update
seems unwise (in my opinion). My idea is to call recenter
only when the line containing point is not centered. I considered using something like count-screen-lines
and recording the line containing point, but I know from experience that vertical-motion
can slow things down when called excessively. I also know that posn-at-point
can slow things down when called excessively, but I figure it will probably suffice for this use-case to help us record the Y-axis containing point. If the Y-axis containing point has changed, then recenter
and record the new Y
and the selected-window
in a variable -- to be compared against future values. Other than reducing the calls to recenter
as in the following example, I cannot think of anything else to reduce screen flickering:
(defvar my-isearch-window-start '(nil 0)
"Record the `selected-window' and the Y-axis coordinate of point each time that
`isearch-update' calls `my-isearch-update-recenter' (via an advice). The value
of this variable will be a cons cell with the CAR being the `selected-window' and
the CDR being the Y-axis coordinate of point.")
(defun my-isearch-update-recenter ()
(let* ((win (selected-window))
(pt (point))
(y (cdr (nth 2 (posn-at-point pt win))))
(same-y-p (and y
(eq win (car my-isearch-window-start))
(= y (cdr my-isearch-window-start)))))
(when (and y (not same-y-p))
(recenter)
(setq my-isearch-window-start (cons win y)))))
(advice-add 'isearch-update :before 'my-isearch-update-recenter)
USAGE:
(1) Open up either a terminal or a GUI version of Emacs 26.3.50, built for the OSX/macOS platform, without any user configuration -- aka /path/to/correct/version/of/Emacs -nw -Q
or drop the -nw
from the command-line if the GUI version is desired. I have tested the code on both a terminal version of Emacs and also a GUI version of Emacs -- the procedure and result should be the same.
[NOTE that many versions of OSX/macOS came with Emacs 22.1.1 pre-installed at /usr/bin/emacs
-- therefore, we want to be sure to launch a current version of Emacs by either using the absolute path to the executable or navigating to its directory and typing ./Emacs ....
In my case, the Emacs executable is inside a packaged Emacs.app directory located at /Applications/Emacs.app/Contents/MacOS/Emacs
]
(2) Copy the code snippets from the answer above, and then switch to the *scratch*
buffer in Emacs and paste the code snippets we just copied, and then type M-x eval-buffer
.
(3) Open a lengthy test file by typing M-x find-library RET simple RET
, which will open the simple.el
library if our version of Emacs was built using the standard defaults that install the Lisp source code.
(4) Type the keyboard shortcut C-s
which is bound to isearch-forward
by default.
(5) isearch-forward
is now active based upon the preceding step. Type the letters: update
. Emacs searches forward for the first occurrence of the letters update
and automatically recenters the screen.
(6) Now we want to search for the next occurrence of the letters update
. To do that, we can either type the keyboard shortcut C-s
or s-g
(aka Command-g) -- both keyboard shortcuts are bound to isearch-repeat-forward
. Emacs searches forward for the next occurrence of the letters update
and recenters the screen.
(7) We can continue repeating the preceding step to verify that everything is working as advertised. This concludes our test.
update_window
except mark dirty rectangles -- the drawing is now done when the OS callsdrawRect
, which in turn callsexpose_frame
. – lawlist Aug 05 '20 at 01:59recenter-bottom
which works pretty good. But when I use the code on my questions, blink occurs after each search , this is the only time I observe this kind of behavior on emacs. – alper Aug 07 '20 at 23:27