Created
October 24, 2018 23:45
-
-
Save aaronjensen/646201d7c971c49112e15facd99d3fca to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 9feb8c763c6bde3f21d4e4638fe9618d4c54474f Mon Sep 17 00:00:00 2001 | |
From: Alan Third <alan@idiocy.org> | |
Date: Sun, 14 Oct 2018 19:12:00 +0100 | |
Subject: [PATCH] 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. | |
--- | |
src/nsterm.m | 80 ++++++++++++++++++++++++---------------------------- | |
1 file changed, 37 insertions(+), 43 deletions(-) | |
diff --git a/src/nsterm.m b/src/nsterm.m | |
index 1ef7f5ab51..bcc23ffeaf 100644 | |
--- a/src/nsterm.m | |
+++ b/src/nsterm.m | |
@@ -279,7 +279,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; | |
@@ -1234,7 +1233,6 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen) | |
NSRectClipList (r, 2); | |
else | |
NSRectClip (*r); | |
- gsaved = YES; | |
return YES; | |
} | |
@@ -1258,11 +1256,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]; | |
} | |
@@ -1288,19 +1282,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. | |
@@ -2837,6 +2818,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)) | |
@@ -2845,10 +2828,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 | |
} | |
} | |
@@ -3233,15 +3227,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: | |
@@ -3275,10 +3260,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 | |
} | |
} | |
@@ -5119,7 +5100,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, | |
@@ -7114,7 +7095,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); | |
} | |
} | |
@@ -8164,8 +8144,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)); | |
@@ -8173,9 +8153,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 (); | |
/* | |
-- | |
2.19.0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment