Subject: bug#2530: 23/NS: redraws according to mouse-face are slow

From: David Reitter <[email-masked]>
Date: Mon, 4 May 2009 18:55:09 -0400

On Apr 23, 2009, at 11:27 PM, Adrian Robert wrote:
>> Does anyone have an idea how to fix issue 2530?  I think this  
>> slowness is quite painful.  In my case, it is the tabbar.el variant  
>> that I'm using that causes this - I'm using several overlays (for a  
>> tab-close button, for instance) that get redrawn one by one.  I  
>> would imagine that this will annoy users in other use cases as well.
>
> Or to ask it another way, is there any reason anyone can think of  
> that redisplay would force calls through the x_draw_glyph_string  
> pathway once for every character when overlays are present?

OK, my observation from tracing this is that it doesn't draw every  
glyph separately, but that it identifies regions of a common face, at  
best a full row of course.  In the case of mouse-face, in the load- 
history-C-j example, we still have a lot of separate strings because  
without the mouse-face, there are still a lot of separate regions.   
The distinction between them may be lost (which is very unfortunate  
from an UI point of view), but the region identification algorithm  
(BUILD_GLYPH_STRINGS I suppose) doesn't see that.

Now, in NS (or at least in Cocoa), there seem to be screen updates  
every time we draw a glyph string. If we wrap the code in  
show_mouse_face in NS[Dis|En]ableScreen, the problem goes away for me  
(and it's not just delayed).
Same for the header-line/overlay issues I reported in #2530.

Note that I'm not claiming that the patch below is the right fix...:

Moving the mouse a bit causes the whole mouse highlight to flicker.
I suspect that it's the same underlying problem.  I wonder if we need  
to wrap more code in NSDisableScreenUpdates.

diff --git a/src/xdisp.c b/src/xdisp.c
index ac989d3..fc319ca 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -22790,6 +22790,10 @@ show_mouse_face (dpyinfo, draw)
    struct window *w = XWINDOW (dpyinfo->mouse_face_window);
    struct frame *f = XFRAME (WINDOW_FRAME (w));

+#ifdef NS_IMPL_COCOA
+  NSDisableScreenUpdates ();
+#endif
+
    if (/* If window is in the process of being destroyed, don't bother
  	 to do anything.  */
        w->current_matrix != NULL
@@ -22852,6 +22856,9 @@ show_mouse_face (dpyinfo, draw)
  	  UNBLOCK_INPUT;
  	}
      }
+#ifdef NS_IMPL_COCOA
+  NSEnableScreenUpdates ();
+#endif

    /* Change the mouse cursor.  */
    if (draw == DRAW_NORMAL_TEXT && !EQ (dpyinfo->mouse_face_window, f- 
 >tool_bar_window))