Fix some NS drawing issues (bug#32932)

* src/nsterm.m (ns_clip_to_rect):
(ns_reset_clipping): Remove gsaved variable and associated code.
(ns_flush_display): Remove function.
(ns_copy_bits): use translateRectsNeedingDisplayInRect:by: to copy any
pending drawing actions along with the image.
([EmacsView windowWillResize:toSize:]): Remove unneeded call.
([EmacsView drawRect:]): Remove redundant call to ns_clear_frame_area,
and optimize the exposed rectangles.
(ns_draw_window_cursor): Remove unneeded disabling of screen updates.
This commit is contained in:
Alan Third 2018-10-14 19:12:00 +01:00
parent d72975a654
commit 7e8eee60a9

View file

@ -277,7 +277,6 @@ - (NSColor *)colorUsingDefaultColorSpace
/* display update */
static int ns_window_num = 0;
static BOOL gsaved = NO;
static BOOL ns_fake_keydown = NO;
#ifdef NS_IMPL_COCOA
static BOOL ns_menu_bar_is_hidden = NO;
@ -1180,7 +1179,6 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
NSRectClipList (r, 2);
else
NSRectClip (*r);
gsaved = YES;
return YES;
}
@ -1204,11 +1202,7 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
{
NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_reset_clipping");
if (gsaved)
{
[[NSGraphicsContext currentContext] restoreGraphicsState];
gsaved = NO;
}
[[NSGraphicsContext currentContext] restoreGraphicsState];
}
@ -1234,19 +1228,6 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
return ns_clip_to_rect (f, &clip_rect, 1);
}
static void
ns_flush_display (struct frame *f)
/* Force the frame to redisplay. If areas have previously been marked
dirty by setNeedsDisplayInRect (in ns_clip_to_rect), then this will call
draw_rect: which will "expose" those areas. */
{
block_input ();
[FRAME_NS_VIEW (f) displayIfNeeded];
unblock_input ();
}
/* ==========================================================================
Visible bell and beep.
@ -2710,6 +2691,8 @@ so some key presses (TAB) are swallowed by the system. */
static void
ns_copy_bits (struct frame *f, NSRect src, NSRect dest)
{
NSSize delta = NSMakeSize (dest.origin.x - src.origin.x,
dest.origin.y - src.origin.y)
NSTRACE ("ns_copy_bits");
if (FRAME_NS_VIEW (f))
@ -2718,10 +2701,21 @@ so some key presses (TAB) are swallowed by the system. */
/* FIXME: scrollRect:by: is deprecated in macOS 10.14. There is
no obvious replacement so we may have to come up with our own. */
[FRAME_NS_VIEW (f) scrollRect: src
by: NSMakeSize (dest.origin.x - src.origin.x,
dest.origin.y - src.origin.y)];
[FRAME_NS_VIEW (f) setNeedsDisplay:YES];
[FRAME_NS_VIEW (f) scrollRect: src by: delta];
#ifdef NS_IMPL_COCOA
/* As far as I can tell from the documentation, scrollRect:by:,
above, should copy the dirty rectangles from our source
rectangle to our destination, however it appears it clips the
operation to src. As a result we need to use
translateRectsNeedingDisplayInRect:by: below, and we have to
union src and dest so it can pick up the dirty rectangles,
and place them, as it also clips to the rectangle.
FIXME: We need a GNUstep equivalent. */
[FRAME_NS_VIEW (f) translateRectsNeedingDisplayInRect:NSUnionRect (src, dest)
by:delta];
#endif
}
}
@ -3106,15 +3100,6 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
else
[FRAME_CURSOR_COLOR (f) set];
#ifdef NS_IMPL_COCOA
/* TODO: This makes drawing of cursor plus that of phys_cursor_glyph
atomic. Cleaner ways of doing this should be investigated.
One way would be to set a global variable DRAWING_CURSOR
when making the call to draw_phys..(), don't focus in that
case, then move the ns_reset_clipping() here after that call. */
NSDisableScreenUpdates ();
#endif
switch (cursor_type)
{
case DEFAULT_CURSOR:
@ -3148,10 +3133,6 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
/* draw the character under the cursor */
if (cursor_type != NO_CURSOR)
draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
#ifdef NS_IMPL_COCOA
NSEnableScreenUpdates ();
#endif
}
}
@ -4977,7 +4958,7 @@ static Lisp_Object ns_string_to_lispmod (const char *s)
ns_after_update_window_line,
ns_update_window_begin,
ns_update_window_end,
ns_flush_display, /* flush_display */
0, /* flush_display */
x_clear_window_mouse_face,
x_get_glyph_overhangs,
x_fix_overlapping_area,
@ -7046,7 +7027,6 @@ - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
size_title = xmalloc (strlen (old_title) + 40);
esprintf (size_title, "%s — (%d x %d)", old_title, cols, rows);
[window setTitle: [NSString stringWithUTF8String: size_title]];
[window display];
xfree (size_title);
}
}
@ -8095,8 +8075,8 @@ - (instancetype)toggleToolbar: (id)sender
- (void)drawRect: (NSRect)rect
{
int x = NSMinX (rect), y = NSMinY (rect);
int width = NSWidth (rect), height = NSHeight (rect);
const NSRect *rectList;
NSInteger numRects;
NSTRACE ("[EmacsView drawRect:" NSTRACE_FMT_RECT "]",
NSTRACE_ARG_RECT(rect));
@ -8104,9 +8084,23 @@ - (void)drawRect: (NSRect)rect
if (!emacsframe || !emacsframe->output_data.ns)
return;
ns_clear_frame_area (emacsframe, x, y, width, height);
block_input ();
expose_frame (emacsframe, x, y, width, height);
/* Get only the precise dirty rectangles to avoid redrawing
potentially large areas of the frame that haven't changed.
I'm not sure this actually provides much of a performance benefit
as it's hard to benchmark, but it certainly doesn't seem to
hurt. */
[self getRectsBeingDrawn:&rectList count:&numRects];
for (int i = 0 ; i < numRects ; i++)
{
NSRect r = rectList[i];
expose_frame (emacsframe,
NSMinX (r), NSMinY (r),
NSWidth (r), NSHeight (r));
}
unblock_input ();
/*