aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlan Third2018-10-29 15:37:35 +0000
committerAlan Third2018-11-25 11:25:33 +0000
commit094fcf62d289f19a4633275812e9e5e500463e91 (patch)
treefacf8757888aebe89fa8aae1a9efe94df7502139 /src
parent9877c03293241091ba4069002d4dc4d74b557414 (diff)
downloademacs-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.m149
-rw-r--r--src/xdisp.c15
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
799static NSRect
800ns_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
1209static BOOL
1210ns_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
2692ns_copy_bits (struct frame *f, NSRect src, NSRect dest) 2668ns_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