diff options
| author | Alan Third | 2018-10-14 19:12:00 +0100 |
|---|---|---|
| committer | Alan Third | 2018-10-24 11:32:23 +0100 |
| commit | 7e8eee60a9dbb0c59cf26f237b21efe7fd1043c9 (patch) | |
| tree | f30088bfeb0bd46f1f0ac420d88c54edc910b758 /src | |
| parent | d72975a654e5effe86625126ba7f2923c8e2f9d2 (diff) | |
| download | emacs-7e8eee60a9dbb0c59cf26f237b21efe7fd1043c9.tar.gz emacs-7e8eee60a9dbb0c59cf26f237b21efe7fd1043c9.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/nsterm.m | 80 |
1 files changed, 37 insertions, 43 deletions
diff --git a/src/nsterm.m b/src/nsterm.m index 8c355a89f8f..4b5d025ee3c 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -277,7 +277,6 @@ long context_menu_value = 0; | |||
| 277 | 277 | ||
| 278 | /* display update */ | 278 | /* display update */ |
| 279 | static int ns_window_num = 0; | 279 | static int ns_window_num = 0; |
| 280 | static BOOL gsaved = NO; | ||
| 281 | static BOOL ns_fake_keydown = NO; | 280 | static BOOL ns_fake_keydown = NO; |
| 282 | #ifdef NS_IMPL_COCOA | 281 | #ifdef NS_IMPL_COCOA |
| 283 | static BOOL ns_menu_bar_is_hidden = NO; | 282 | static BOOL ns_menu_bar_is_hidden = NO; |
| @@ -1180,7 +1179,6 @@ ns_clip_to_rect (struct frame *f, NSRect *r, int n) | |||
| 1180 | NSRectClipList (r, 2); | 1179 | NSRectClipList (r, 2); |
| 1181 | else | 1180 | else |
| 1182 | NSRectClip (*r); | 1181 | NSRectClip (*r); |
| 1183 | gsaved = YES; | ||
| 1184 | 1182 | ||
| 1185 | return YES; | 1183 | return YES; |
| 1186 | } | 1184 | } |
| @@ -1204,11 +1202,7 @@ ns_reset_clipping (struct frame *f) | |||
| 1204 | { | 1202 | { |
| 1205 | NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_reset_clipping"); | 1203 | NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_reset_clipping"); |
| 1206 | 1204 | ||
| 1207 | if (gsaved) | 1205 | [[NSGraphicsContext currentContext] restoreGraphicsState]; |
| 1208 | { | ||
| 1209 | [[NSGraphicsContext currentContext] restoreGraphicsState]; | ||
| 1210 | gsaved = NO; | ||
| 1211 | } | ||
| 1212 | } | 1206 | } |
| 1213 | 1207 | ||
| 1214 | 1208 | ||
| @@ -1234,19 +1228,6 @@ ns_clip_to_row (struct window *w, struct glyph_row *row, | |||
| 1234 | return ns_clip_to_rect (f, &clip_rect, 1); | 1228 | return ns_clip_to_rect (f, &clip_rect, 1); |
| 1235 | } | 1229 | } |
| 1236 | 1230 | ||
| 1237 | |||
| 1238 | static void | ||
| 1239 | ns_flush_display (struct frame *f) | ||
| 1240 | /* Force the frame to redisplay. If areas have previously been marked | ||
| 1241 | dirty by setNeedsDisplayInRect (in ns_clip_to_rect), then this will call | ||
| 1242 | draw_rect: which will "expose" those areas. */ | ||
| 1243 | { | ||
| 1244 | block_input (); | ||
| 1245 | [FRAME_NS_VIEW (f) displayIfNeeded]; | ||
| 1246 | unblock_input (); | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | |||
| 1250 | /* ========================================================================== | 1231 | /* ========================================================================== |
| 1251 | 1232 | ||
| 1252 | Visible bell and beep. | 1233 | Visible bell and beep. |
| @@ -2710,6 +2691,8 @@ ns_clear_frame_area (struct frame *f, int x, int y, int width, int height) | |||
| 2710 | static void | 2691 | static void |
| 2711 | ns_copy_bits (struct frame *f, NSRect src, NSRect dest) | 2692 | ns_copy_bits (struct frame *f, NSRect src, NSRect dest) |
| 2712 | { | 2693 | { |
| 2694 | NSSize delta = NSMakeSize (dest.origin.x - src.origin.x, | ||
| 2695 | dest.origin.y - src.origin.y) | ||
| 2713 | NSTRACE ("ns_copy_bits"); | 2696 | NSTRACE ("ns_copy_bits"); |
| 2714 | 2697 | ||
| 2715 | if (FRAME_NS_VIEW (f)) | 2698 | if (FRAME_NS_VIEW (f)) |
| @@ -2718,10 +2701,21 @@ ns_copy_bits (struct frame *f, NSRect src, NSRect dest) | |||
| 2718 | 2701 | ||
| 2719 | /* FIXME: scrollRect:by: is deprecated in macOS 10.14. There is | 2702 | /* FIXME: scrollRect:by: is deprecated in macOS 10.14. There is |
| 2720 | no obvious replacement so we may have to come up with our own. */ | 2703 | no obvious replacement so we may have to come up with our own. */ |
| 2721 | [FRAME_NS_VIEW (f) scrollRect: src | 2704 | [FRAME_NS_VIEW (f) scrollRect: src by: delta]; |
| 2722 | by: NSMakeSize (dest.origin.x - src.origin.x, | 2705 | |
| 2723 | dest.origin.y - src.origin.y)]; | 2706 | #ifdef NS_IMPL_COCOA |
| 2724 | [FRAME_NS_VIEW (f) setNeedsDisplay:YES]; | 2707 | /* As far as I can tell from the documentation, scrollRect:by:, |
| 2708 | above, should copy the dirty rectangles from our source | ||
| 2709 | rectangle to our destination, however it appears it clips the | ||
| 2710 | operation to src. As a result we need to use | ||
| 2711 | translateRectsNeedingDisplayInRect:by: below, and we have to | ||
| 2712 | union src and dest so it can pick up the dirty rectangles, | ||
| 2713 | and place them, as it also clips to the rectangle. | ||
| 2714 | |||
| 2715 | FIXME: We need a GNUstep equivalent. */ | ||
| 2716 | [FRAME_NS_VIEW (f) translateRectsNeedingDisplayInRect:NSUnionRect (src, dest) | ||
| 2717 | by:delta]; | ||
| 2718 | #endif | ||
| 2725 | } | 2719 | } |
| 2726 | } | 2720 | } |
| 2727 | 2721 | ||
| @@ -3106,15 +3100,6 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, | |||
| 3106 | else | 3100 | else |
| 3107 | [FRAME_CURSOR_COLOR (f) set]; | 3101 | [FRAME_CURSOR_COLOR (f) set]; |
| 3108 | 3102 | ||
| 3109 | #ifdef NS_IMPL_COCOA | ||
| 3110 | /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph | ||
| 3111 | atomic. Cleaner ways of doing this should be investigated. | ||
| 3112 | One way would be to set a global variable DRAWING_CURSOR | ||
| 3113 | when making the call to draw_phys..(), don't focus in that | ||
| 3114 | case, then move the ns_reset_clipping() here after that call. */ | ||
| 3115 | NSDisableScreenUpdates (); | ||
| 3116 | #endif | ||
| 3117 | |||
| 3118 | switch (cursor_type) | 3103 | switch (cursor_type) |
| 3119 | { | 3104 | { |
| 3120 | case DEFAULT_CURSOR: | 3105 | case DEFAULT_CURSOR: |
| @@ -3148,10 +3133,6 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, | |||
| 3148 | /* draw the character under the cursor */ | 3133 | /* draw the character under the cursor */ |
| 3149 | if (cursor_type != NO_CURSOR) | 3134 | if (cursor_type != NO_CURSOR) |
| 3150 | draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); | 3135 | draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); |
| 3151 | |||
| 3152 | #ifdef NS_IMPL_COCOA | ||
| 3153 | NSEnableScreenUpdates (); | ||
| 3154 | #endif | ||
| 3155 | } | 3136 | } |
| 3156 | } | 3137 | } |
| 3157 | 3138 | ||
| @@ -4977,7 +4958,7 @@ static struct redisplay_interface ns_redisplay_interface = | |||
| 4977 | ns_after_update_window_line, | 4958 | ns_after_update_window_line, |
| 4978 | ns_update_window_begin, | 4959 | ns_update_window_begin, |
| 4979 | ns_update_window_end, | 4960 | ns_update_window_end, |
| 4980 | ns_flush_display, /* flush_display */ | 4961 | 0, /* flush_display */ |
| 4981 | x_clear_window_mouse_face, | 4962 | x_clear_window_mouse_face, |
| 4982 | x_get_glyph_overhangs, | 4963 | x_get_glyph_overhangs, |
| 4983 | x_fix_overlapping_area, | 4964 | x_fix_overlapping_area, |
| @@ -7046,7 +7027,6 @@ not_in_argv (NSString *arg) | |||
| 7046 | size_title = xmalloc (strlen (old_title) + 40); | 7027 | size_title = xmalloc (strlen (old_title) + 40); |
| 7047 | esprintf (size_title, "%s — (%d x %d)", old_title, cols, rows); | 7028 | esprintf (size_title, "%s — (%d x %d)", old_title, cols, rows); |
| 7048 | [window setTitle: [NSString stringWithUTF8String: size_title]]; | 7029 | [window setTitle: [NSString stringWithUTF8String: size_title]]; |
| 7049 | [window display]; | ||
| 7050 | xfree (size_title); | 7030 | xfree (size_title); |
| 7051 | } | 7031 | } |
| 7052 | } | 7032 | } |
| @@ -8095,8 +8075,8 @@ not_in_argv (NSString *arg) | |||
| 8095 | 8075 | ||
| 8096 | - (void)drawRect: (NSRect)rect | 8076 | - (void)drawRect: (NSRect)rect |
| 8097 | { | 8077 | { |
| 8098 | int x = NSMinX (rect), y = NSMinY (rect); | 8078 | const NSRect *rectList; |
| 8099 | int width = NSWidth (rect), height = NSHeight (rect); | 8079 | NSInteger numRects; |
| 8100 | 8080 | ||
| 8101 | NSTRACE ("[EmacsView drawRect:" NSTRACE_FMT_RECT "]", | 8081 | NSTRACE ("[EmacsView drawRect:" NSTRACE_FMT_RECT "]", |
| 8102 | NSTRACE_ARG_RECT(rect)); | 8082 | NSTRACE_ARG_RECT(rect)); |
| @@ -8104,9 +8084,23 @@ not_in_argv (NSString *arg) | |||
| 8104 | if (!emacsframe || !emacsframe->output_data.ns) | 8084 | if (!emacsframe || !emacsframe->output_data.ns) |
| 8105 | return; | 8085 | return; |
| 8106 | 8086 | ||
| 8107 | ns_clear_frame_area (emacsframe, x, y, width, height); | ||
| 8108 | block_input (); | 8087 | block_input (); |
| 8109 | expose_frame (emacsframe, x, y, width, height); | 8088 | |
| 8089 | /* Get only the precise dirty rectangles to avoid redrawing | ||
| 8090 | potentially large areas of the frame that haven't changed. | ||
| 8091 | |||
| 8092 | I'm not sure this actually provides much of a performance benefit | ||
| 8093 | as it's hard to benchmark, but it certainly doesn't seem to | ||
| 8094 | hurt. */ | ||
| 8095 | [self getRectsBeingDrawn:&rectList count:&numRects]; | ||
| 8096 | for (int i = 0 ; i < numRects ; i++) | ||
| 8097 | { | ||
| 8098 | NSRect r = rectList[i]; | ||
| 8099 | expose_frame (emacsframe, | ||
| 8100 | NSMinX (r), NSMinY (r), | ||
| 8101 | NSWidth (r), NSHeight (r)); | ||
| 8102 | } | ||
| 8103 | |||
| 8110 | unblock_input (); | 8104 | unblock_input (); |
| 8111 | 8105 | ||
| 8112 | /* | 8106 | /* |