diff options
| author | Alan Third | 2018-10-29 15:37:35 +0000 |
|---|---|---|
| committer | Alan Third | 2018-11-25 11:25:33 +0000 |
| commit | 094fcf62d289f19a4633275812e9e5e500463e91 (patch) | |
| tree | facf8757888aebe89fa8aae1a9efe94df7502139 /src | |
| parent | 9877c03293241091ba4069002d4dc4d74b557414 (diff) | |
| download | emacs-094fcf62d289f19a4633275812e9e5e500463e91.tar.gz emacs-094fcf62d289f19a4633275812e9e5e500463e91.zip | |
Fix more drawing bugs in NS port (bug#32932)
* src/nsterm.m (ns_row_rect): New function.
(ns_clip_to_row): Remove function.
(ns_copy_bits): Fix mistake.
(ns_shift_glyphs_for_insert): Mark the frame as dirty instead of
directly copying.
(ns_draw_fringe_bitmap): Stop using ns_clip_to_row.
(ns_draw_window_cursor): Stop using ns_clip_to_row and perform a
display when not in redisplay.
(ns_update_window_begin): Remove redundant code that never executes.
([EmacsView drawRect:]): Show the rectangle being exposed in NSTRACE.
* src/xdisp.c (expose_window_tree) [HAVE_NS]:
(expose_frame) [HAVE_NS]: Redraw even if the frame is garbaged.
Diffstat (limited to 'src')
| -rw-r--r-- | src/nsterm.m | 149 | ||||
| -rw-r--r-- | src/xdisp.c | 15 |
2 files changed, 91 insertions, 73 deletions
diff --git a/src/nsterm.m b/src/nsterm.m index 4b5d025ee3c..948dd1da2e1 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -796,6 +796,27 @@ ns_menu_bar_height (NSScreen *screen) | |||
| 796 | } | 796 | } |
| 797 | 797 | ||
| 798 | 798 | ||
| 799 | static NSRect | ||
| 800 | ns_row_rect (struct window *w, struct glyph_row *row, | ||
| 801 | enum glyph_row_area area) | ||
| 802 | /* Get the row as an NSRect. */ | ||
| 803 | { | ||
| 804 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | ||
| 805 | NSRect rect; | ||
| 806 | int window_x, window_y, window_width; | ||
| 807 | |||
| 808 | window_box (w, area, &window_x, &window_y, &window_width, 0); | ||
| 809 | |||
| 810 | rect.origin.x = window_x; | ||
| 811 | rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y)); | ||
| 812 | rect.origin.y = max (rect.origin.y, window_y); | ||
| 813 | rect.size.width = window_width; | ||
| 814 | rect.size.height = row->visible_height; | ||
| 815 | |||
| 816 | return rect; | ||
| 817 | } | ||
| 818 | |||
| 819 | |||
| 799 | /* ========================================================================== | 820 | /* ========================================================================== |
| 800 | 821 | ||
| 801 | Focus (clipping) and screen update | 822 | Focus (clipping) and screen update |
| @@ -1048,29 +1069,6 @@ ns_update_begin (struct frame *f) | |||
| 1048 | if (! tbar_visible != ! [toolbar isVisible]) | 1069 | if (! tbar_visible != ! [toolbar isVisible]) |
| 1049 | [toolbar setVisible: tbar_visible]; | 1070 | [toolbar setVisible: tbar_visible]; |
| 1050 | } | 1071 | } |
| 1051 | |||
| 1052 | /* drawRect may have been called for say the minibuffer, and then clip path | ||
| 1053 | is for the minibuffer. But the display engine may draw more because | ||
| 1054 | we have set the frame as garbaged. So reset clip path to the whole | ||
| 1055 | view. */ | ||
| 1056 | /* FIXME: I don't think we need to do this. */ | ||
| 1057 | if ([NSView focusView] == FRAME_NS_VIEW (f)) | ||
| 1058 | { | ||
| 1059 | NSBezierPath *bp; | ||
| 1060 | NSRect r = [view frame]; | ||
| 1061 | NSRect cr = [[view window] frame]; | ||
| 1062 | /* If a large frame size is set, r may be larger than the window frame | ||
| 1063 | before constrained. In that case don't change the clip path, as we | ||
| 1064 | will clear in to the tool bar and title bar. */ | ||
| 1065 | if (r.size.height | ||
| 1066 | + FRAME_NS_TITLEBAR_HEIGHT (f) | ||
| 1067 | + FRAME_TOOLBAR_HEIGHT (f) <= cr.size.height) | ||
| 1068 | { | ||
| 1069 | bp = [[NSBezierPath bezierPathWithRect: r] retain]; | ||
| 1070 | [bp setClip]; | ||
| 1071 | [bp release]; | ||
| 1072 | } | ||
| 1073 | } | ||
| 1074 | #endif | 1072 | #endif |
| 1075 | } | 1073 | } |
| 1076 | 1074 | ||
| @@ -1206,28 +1204,6 @@ ns_reset_clipping (struct frame *f) | |||
| 1206 | } | 1204 | } |
| 1207 | 1205 | ||
| 1208 | 1206 | ||
| 1209 | static BOOL | ||
| 1210 | ns_clip_to_row (struct window *w, struct glyph_row *row, | ||
| 1211 | enum glyph_row_area area, BOOL gc) | ||
| 1212 | /* -------------------------------------------------------------------------- | ||
| 1213 | Internal (but parallels other terms): Focus drawing on given row | ||
| 1214 | -------------------------------------------------------------------------- */ | ||
| 1215 | { | ||
| 1216 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | ||
| 1217 | NSRect clip_rect; | ||
| 1218 | int window_x, window_y, window_width; | ||
| 1219 | |||
| 1220 | window_box (w, area, &window_x, &window_y, &window_width, 0); | ||
| 1221 | |||
| 1222 | clip_rect.origin.x = window_x; | ||
| 1223 | clip_rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y)); | ||
| 1224 | clip_rect.origin.y = max (clip_rect.origin.y, window_y); | ||
| 1225 | clip_rect.size.width = window_width; | ||
| 1226 | clip_rect.size.height = row->visible_height; | ||
| 1227 | |||
| 1228 | return ns_clip_to_rect (f, &clip_rect, 1); | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | /* ========================================================================== | 1207 | /* ========================================================================== |
| 1232 | 1208 | ||
| 1233 | Visible bell and beep. | 1209 | Visible bell and beep. |
| @@ -2692,7 +2668,7 @@ static void | |||
| 2692 | ns_copy_bits (struct frame *f, NSRect src, NSRect dest) | 2668 | ns_copy_bits (struct frame *f, NSRect src, NSRect dest) |
| 2693 | { | 2669 | { |
| 2694 | NSSize delta = NSMakeSize (dest.origin.x - src.origin.x, | 2670 | NSSize delta = NSMakeSize (dest.origin.x - src.origin.x, |
| 2695 | dest.origin.y - src.origin.y) | 2671 | dest.origin.y - src.origin.y); |
| 2696 | NSTRACE ("ns_copy_bits"); | 2672 | NSTRACE ("ns_copy_bits"); |
| 2697 | 2673 | ||
| 2698 | if (FRAME_NS_VIEW (f)) | 2674 | if (FRAME_NS_VIEW (f)) |
| @@ -2825,12 +2801,20 @@ ns_shift_glyphs_for_insert (struct frame *f, | |||
| 2825 | External (RIF): copy an area horizontally, don't worry about clearing src | 2801 | External (RIF): copy an area horizontally, don't worry about clearing src |
| 2826 | -------------------------------------------------------------------------- */ | 2802 | -------------------------------------------------------------------------- */ |
| 2827 | { | 2803 | { |
| 2828 | NSRect srcRect = NSMakeRect (x, y, width, height); | 2804 | //NSRect srcRect = NSMakeRect (x, y, width, height); |
| 2829 | NSRect dstRect = NSMakeRect (x+shift_by, y, width, height); | 2805 | NSRect dstRect = NSMakeRect (x+shift_by, y, width, height); |
| 2830 | 2806 | ||
| 2831 | NSTRACE ("ns_shift_glyphs_for_insert"); | 2807 | NSTRACE ("ns_shift_glyphs_for_insert"); |
| 2832 | 2808 | ||
| 2833 | ns_copy_bits (f, srcRect, dstRect); | 2809 | /* This doesn't work now as we copy the "bits" before we've had a |
| 2810 | chance to actually draw any changes to the screen. This means in | ||
| 2811 | certain circumstances we end up with copies of the cursor all | ||
| 2812 | over the place. Just mark the area dirty so it is redrawn later. | ||
| 2813 | |||
| 2814 | FIXME: Work out how to do this properly. */ | ||
| 2815 | // ns_copy_bits (f, srcRect, dstRect); | ||
| 2816 | |||
| 2817 | [FRAME_NS_VIEW (f) setNeedsDisplayInRect:dstRect]; | ||
| 2834 | } | 2818 | } |
| 2835 | 2819 | ||
| 2836 | 2820 | ||
| @@ -2911,6 +2895,9 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 2911 | struct face *face = p->face; | 2895 | struct face *face = p->face; |
| 2912 | static EmacsImage **bimgs = NULL; | 2896 | static EmacsImage **bimgs = NULL; |
| 2913 | static int nBimgs = 0; | 2897 | static int nBimgs = 0; |
| 2898 | NSRect clearRect = NSZeroRect; | ||
| 2899 | NSRect imageRect = NSZeroRect; | ||
| 2900 | NSRect rowRect = ns_row_rect (w, row, ANY_AREA); | ||
| 2914 | 2901 | ||
| 2915 | NSTRACE_WHEN (NSTRACE_GROUP_FRINGE, "ns_draw_fringe_bitmap"); | 2902 | NSTRACE_WHEN (NSTRACE_GROUP_FRINGE, "ns_draw_fringe_bitmap"); |
| 2916 | NSTRACE_MSG ("which:%d cursor:%d overlay:%d width:%d height:%d period:%d", | 2903 | NSTRACE_MSG ("which:%d cursor:%d overlay:%d width:%d height:%d period:%d", |
| @@ -2925,25 +2912,40 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 2925 | nBimgs = max_used_fringe_bitmap; | 2912 | nBimgs = max_used_fringe_bitmap; |
| 2926 | } | 2913 | } |
| 2927 | 2914 | ||
| 2928 | /* Must clip because of partially visible lines. */ | 2915 | /* Work out the rectangle we will composite into. */ |
| 2929 | if (ns_clip_to_row (w, row, ANY_AREA, YES)) | 2916 | if (p->which) |
| 2917 | imageRect = NSMakeRect (p->x, p->y, p->wd, p->h); | ||
| 2918 | |||
| 2919 | /* Work out the rectangle we will need to clear. Because we're | ||
| 2920 | compositing rather than blitting, we need to clear the area under | ||
| 2921 | the image regardless of anything else. */ | ||
| 2922 | if (!p->overlay_p) | ||
| 2923 | { | ||
| 2924 | clearRect = NSMakeRect (p->bx, p->by, p->nx, p->ny); | ||
| 2925 | clearRect = NSUnionRect (clearRect, imageRect); | ||
| 2926 | } | ||
| 2927 | else | ||
| 2928 | { | ||
| 2929 | clearRect = imageRect; | ||
| 2930 | } | ||
| 2931 | |||
| 2932 | /* Handle partially visible rows. */ | ||
| 2933 | clearRect = NSIntersectionRect (clearRect, rowRect); | ||
| 2934 | |||
| 2935 | /* The visible portion of imageRect will always be contained within | ||
| 2936 | clearRect. */ | ||
| 2937 | if (ns_clip_to_rect (f, &clearRect, 1)) | ||
| 2930 | { | 2938 | { |
| 2931 | if (!p->overlay_p) | 2939 | if (! NSIsEmptyRect (clearRect)) |
| 2932 | { | 2940 | { |
| 2933 | int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny; | 2941 | NSTRACE_RECT ("clearRect", clearRect); |
| 2934 | 2942 | ||
| 2935 | if (bx >= 0 && nx > 0) | 2943 | [ns_lookup_indexed_color(face->background, f) set]; |
| 2936 | { | 2944 | NSRectFill (clearRect); |
| 2937 | NSRect r = NSMakeRect (bx, by, nx, ny); | ||
| 2938 | NSRectClip (r); | ||
| 2939 | [ns_lookup_indexed_color (face->background, f) set]; | ||
| 2940 | NSRectFill (r); | ||
| 2941 | } | ||
| 2942 | } | 2945 | } |
| 2943 | 2946 | ||
| 2944 | if (p->which) | 2947 | if (p->which) |
| 2945 | { | 2948 | { |
| 2946 | NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h); | ||
| 2947 | EmacsImage *img = bimgs[p->which - 1]; | 2949 | EmacsImage *img = bimgs[p->which - 1]; |
| 2948 | 2950 | ||
| 2949 | if (!img) | 2951 | if (!img) |
| @@ -2964,13 +2966,6 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 2964 | xfree (cbits); | 2966 | xfree (cbits); |
| 2965 | } | 2967 | } |
| 2966 | 2968 | ||
| 2967 | NSTRACE_RECT ("r", r); | ||
| 2968 | |||
| 2969 | NSRectClip (r); | ||
| 2970 | /* Since we composite the bitmap instead of just blitting it, we need | ||
| 2971 | to erase the whole background. */ | ||
| 2972 | [ns_lookup_indexed_color(face->background, f) set]; | ||
| 2973 | NSRectFill (r); | ||
| 2974 | 2969 | ||
| 2975 | { | 2970 | { |
| 2976 | NSColor *bm_color; | 2971 | NSColor *bm_color; |
| @@ -2990,7 +2985,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 2990 | 2985 | ||
| 2991 | NSTRACE_RECT ("fromRect", fromRect); | 2986 | NSTRACE_RECT ("fromRect", fromRect); |
| 2992 | 2987 | ||
| 2993 | [img drawInRect: r | 2988 | [img drawInRect: imageRect |
| 2994 | fromRect: fromRect | 2989 | fromRect: fromRect |
| 2995 | operation: NSCompositingOperationSourceOver | 2990 | operation: NSCompositingOperationSourceOver |
| 2996 | fraction: 1.0 | 2991 | fraction: 1.0 |
| @@ -2998,7 +2993,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 2998 | hints: nil]; | 2993 | hints: nil]; |
| 2999 | #else | 2994 | #else |
| 3000 | { | 2995 | { |
| 3001 | NSPoint pt = r.origin; | 2996 | NSPoint pt = imageRect.origin; |
| 3002 | pt.y += p->h; | 2997 | pt.y += p->h; |
| 3003 | [img compositeToPoint: pt operation: NSCompositingOperationSourceOver]; | 2998 | [img compositeToPoint: pt operation: NSCompositingOperationSourceOver]; |
| 3004 | } | 2999 | } |
| @@ -3088,7 +3083,9 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, | |||
| 3088 | r.size.width = w->phys_cursor_width; | 3083 | r.size.width = w->phys_cursor_width; |
| 3089 | 3084 | ||
| 3090 | /* Prevent the cursor from being drawn outside the text area. */ | 3085 | /* Prevent the cursor from being drawn outside the text area. */ |
| 3091 | if (ns_clip_to_row (w, glyph_row, TEXT_AREA, NO)) | 3086 | r = NSIntersectionRect (r, ns_row_rect (w, glyph_row, TEXT_AREA)); |
| 3087 | |||
| 3088 | if (ns_clip_to_rect (f, &r, 1)) | ||
| 3092 | { | 3089 | { |
| 3093 | face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id); | 3090 | face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id); |
| 3094 | if (face && NS_FACE_BACKGROUND (face) | 3091 | if (face && NS_FACE_BACKGROUND (face) |
| @@ -3128,11 +3125,18 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, | |||
| 3128 | NSRectFill (s); | 3125 | NSRectFill (s); |
| 3129 | break; | 3126 | break; |
| 3130 | } | 3127 | } |
| 3131 | ns_reset_clipping (f); | ||
| 3132 | 3128 | ||
| 3133 | /* draw the character under the cursor */ | 3129 | /* draw the character under the cursor */ |
| 3134 | if (cursor_type != NO_CURSOR) | 3130 | if (cursor_type != NO_CURSOR) |
| 3135 | draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); | 3131 | draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); |
| 3132 | |||
| 3133 | ns_reset_clipping (f); | ||
| 3134 | } | ||
| 3135 | else if (! redisplaying_p) | ||
| 3136 | { | ||
| 3137 | /* If this function is called outside redisplay, it probably | ||
| 3138 | means we need an immediate update. */ | ||
| 3139 | [FRAME_NS_VIEW (f) display]; | ||
| 3136 | } | 3140 | } |
| 3137 | } | 3141 | } |
| 3138 | 3142 | ||
| @@ -8096,6 +8100,9 @@ not_in_argv (NSString *arg) | |||
| 8096 | for (int i = 0 ; i < numRects ; i++) | 8100 | for (int i = 0 ; i < numRects ; i++) |
| 8097 | { | 8101 | { |
| 8098 | NSRect r = rectList[i]; | 8102 | NSRect r = rectList[i]; |
| 8103 | |||
| 8104 | NSTRACE_RECT ("r", r); | ||
| 8105 | |||
| 8099 | expose_frame (emacsframe, | 8106 | expose_frame (emacsframe, |
| 8100 | NSMinX (r), NSMinY (r), | 8107 | NSMinX (r), NSMinY (r), |
| 8101 | NSWidth (r), NSHeight (r)); | 8108 | NSWidth (r), NSHeight (r)); |
diff --git a/src/xdisp.c b/src/xdisp.c index 357f0fb30cd..808eab7e538 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -32258,7 +32258,14 @@ expose_window_tree (struct window *w, XRectangle *r) | |||
| 32258 | struct frame *f = XFRAME (w->frame); | 32258 | struct frame *f = XFRAME (w->frame); |
| 32259 | bool mouse_face_overwritten_p = false; | 32259 | bool mouse_face_overwritten_p = false; |
| 32260 | 32260 | ||
| 32261 | while (w && !FRAME_GARBAGED_P (f)) | 32261 | /* NS toolkits may have aleady modified the frame in expectation of |
| 32262 | a successful redraw, so don't bail out here if the frame is | ||
| 32263 | garbaged. */ | ||
| 32264 | while (w | ||
| 32265 | #if !defined (HAVE_NS) | ||
| 32266 | && !FRAME_GARBAGED_P (f) | ||
| 32267 | #endif | ||
| 32268 | ) | ||
| 32262 | { | 32269 | { |
| 32263 | mouse_face_overwritten_p | 32270 | mouse_face_overwritten_p |
| 32264 | |= (WINDOWP (w->contents) | 32271 | |= (WINDOWP (w->contents) |
| @@ -32286,12 +32293,16 @@ expose_frame (struct frame *f, int x, int y, int w, int h) | |||
| 32286 | 32293 | ||
| 32287 | TRACE ((stderr, "expose_frame ")); | 32294 | TRACE ((stderr, "expose_frame ")); |
| 32288 | 32295 | ||
| 32289 | /* No need to redraw if frame will be redrawn soon. */ | 32296 | #if !defined (HAVE_NS) |
| 32297 | /* No need to redraw if frame will be redrawn soon except under NS | ||
| 32298 | where the toolkit may have already modified the frame in | ||
| 32299 | expectation of us redrawing it. */ | ||
| 32290 | if (FRAME_GARBAGED_P (f)) | 32300 | if (FRAME_GARBAGED_P (f)) |
| 32291 | { | 32301 | { |
| 32292 | TRACE ((stderr, " garbaged\n")); | 32302 | TRACE ((stderr, " garbaged\n")); |
| 32293 | return; | 32303 | return; |
| 32294 | } | 32304 | } |
| 32305 | #endif | ||
| 32295 | 32306 | ||
| 32296 | /* If basic faces haven't been realized yet, there is no point in | 32307 | /* If basic faces haven't been realized yet, there is no point in |
| 32297 | trying to redraw anything. This can happen when we get an expose | 32308 | trying to redraw anything. This can happen when we get an expose |