diff options
| author | Glenn Morris | 2018-11-28 07:51:11 -0800 |
|---|---|---|
| committer | Glenn Morris | 2018-11-28 07:51:11 -0800 |
| commit | b58e8b82ededfb314e385d97df1efed2ce84f4db (patch) | |
| tree | 2f8caac832104f1825349740693e1497e50b6a4e /src | |
| parent | febdedfa8d43258edc4e0f2debd3910e073e9326 (diff) | |
| parent | 094fcf62d289f19a4633275812e9e5e500463e91 (diff) | |
| download | emacs-b58e8b82ededfb314e385d97df1efed2ce84f4db.tar.gz emacs-b58e8b82ededfb314e385d97df1efed2ce84f4db.zip | |
Merge from origin/emacs-26
094fcf6 Fix more drawing bugs in NS port (bug#32932)
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 bcc23ffeaff..07978c0d3b8 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -850,6 +850,27 @@ ns_menu_bar_height (NSScreen *screen) | |||
| 850 | } | 850 | } |
| 851 | 851 | ||
| 852 | 852 | ||
| 853 | static NSRect | ||
| 854 | ns_row_rect (struct window *w, struct glyph_row *row, | ||
| 855 | enum glyph_row_area area) | ||
| 856 | /* Get the row as an NSRect. */ | ||
| 857 | { | ||
| 858 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | ||
| 859 | NSRect rect; | ||
| 860 | int window_x, window_y, window_width; | ||
| 861 | |||
| 862 | window_box (w, area, &window_x, &window_y, &window_width, 0); | ||
| 863 | |||
| 864 | rect.origin.x = window_x; | ||
| 865 | rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y)); | ||
| 866 | rect.origin.y = max (rect.origin.y, window_y); | ||
| 867 | rect.size.width = window_width; | ||
| 868 | rect.size.height = row->visible_height; | ||
| 869 | |||
| 870 | return rect; | ||
| 871 | } | ||
| 872 | |||
| 873 | |||
| 853 | /* ========================================================================== | 874 | /* ========================================================================== |
| 854 | 875 | ||
| 855 | Focus (clipping) and screen update | 876 | Focus (clipping) and screen update |
| @@ -1102,29 +1123,6 @@ ns_update_begin (struct frame *f) | |||
| 1102 | if (! tbar_visible != ! [toolbar isVisible]) | 1123 | if (! tbar_visible != ! [toolbar isVisible]) |
| 1103 | [toolbar setVisible: tbar_visible]; | 1124 | [toolbar setVisible: tbar_visible]; |
| 1104 | } | 1125 | } |
| 1105 | |||
| 1106 | /* drawRect may have been called for say the minibuffer, and then clip path | ||
| 1107 | is for the minibuffer. But the display engine may draw more because | ||
| 1108 | we have set the frame as garbaged. So reset clip path to the whole | ||
| 1109 | view. */ | ||
| 1110 | /* FIXME: I don't think we need to do this. */ | ||
| 1111 | if ([NSView focusView] == FRAME_NS_VIEW (f)) | ||
| 1112 | { | ||
| 1113 | NSBezierPath *bp; | ||
| 1114 | NSRect r = [view frame]; | ||
| 1115 | NSRect cr = [[view window] frame]; | ||
| 1116 | /* If a large frame size is set, r may be larger than the window frame | ||
| 1117 | before constrained. In that case don't change the clip path, as we | ||
| 1118 | will clear in to the tool bar and title bar. */ | ||
| 1119 | if (r.size.height | ||
| 1120 | + FRAME_NS_TITLEBAR_HEIGHT (f) | ||
| 1121 | + FRAME_TOOLBAR_HEIGHT (f) <= cr.size.height) | ||
| 1122 | { | ||
| 1123 | bp = [[NSBezierPath bezierPathWithRect: r] retain]; | ||
| 1124 | [bp setClip]; | ||
| 1125 | [bp release]; | ||
| 1126 | } | ||
| 1127 | } | ||
| 1128 | #endif | 1126 | #endif |
| 1129 | } | 1127 | } |
| 1130 | 1128 | ||
| @@ -1260,28 +1258,6 @@ ns_reset_clipping (struct frame *f) | |||
| 1260 | } | 1258 | } |
| 1261 | 1259 | ||
| 1262 | 1260 | ||
| 1263 | static BOOL | ||
| 1264 | ns_clip_to_row (struct window *w, struct glyph_row *row, | ||
| 1265 | enum glyph_row_area area, BOOL gc) | ||
| 1266 | /* -------------------------------------------------------------------------- | ||
| 1267 | Internal (but parallels other terms): Focus drawing on given row | ||
| 1268 | -------------------------------------------------------------------------- */ | ||
| 1269 | { | ||
| 1270 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | ||
| 1271 | NSRect clip_rect; | ||
| 1272 | int window_x, window_y, window_width; | ||
| 1273 | |||
| 1274 | window_box (w, area, &window_x, &window_y, &window_width, 0); | ||
| 1275 | |||
| 1276 | clip_rect.origin.x = window_x; | ||
| 1277 | clip_rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y)); | ||
| 1278 | clip_rect.origin.y = max (clip_rect.origin.y, window_y); | ||
| 1279 | clip_rect.size.width = window_width; | ||
| 1280 | clip_rect.size.height = row->visible_height; | ||
| 1281 | |||
| 1282 | return ns_clip_to_rect (f, &clip_rect, 1); | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | /* ========================================================================== | 1261 | /* ========================================================================== |
| 1286 | 1262 | ||
| 1287 | Visible bell and beep. | 1263 | Visible bell and beep. |
| @@ -2819,7 +2795,7 @@ static void | |||
| 2819 | ns_copy_bits (struct frame *f, NSRect src, NSRect dest) | 2795 | ns_copy_bits (struct frame *f, NSRect src, NSRect dest) |
| 2820 | { | 2796 | { |
| 2821 | NSSize delta = NSMakeSize (dest.origin.x - src.origin.x, | 2797 | NSSize delta = NSMakeSize (dest.origin.x - src.origin.x, |
| 2822 | dest.origin.y - src.origin.y) | 2798 | dest.origin.y - src.origin.y); |
| 2823 | NSTRACE ("ns_copy_bits"); | 2799 | NSTRACE ("ns_copy_bits"); |
| 2824 | 2800 | ||
| 2825 | if (FRAME_NS_VIEW (f)) | 2801 | if (FRAME_NS_VIEW (f)) |
| @@ -2952,12 +2928,20 @@ ns_shift_glyphs_for_insert (struct frame *f, | |||
| 2952 | External (RIF): copy an area horizontally, don't worry about clearing src | 2928 | External (RIF): copy an area horizontally, don't worry about clearing src |
| 2953 | -------------------------------------------------------------------------- */ | 2929 | -------------------------------------------------------------------------- */ |
| 2954 | { | 2930 | { |
| 2955 | NSRect srcRect = NSMakeRect (x, y, width, height); | 2931 | //NSRect srcRect = NSMakeRect (x, y, width, height); |
| 2956 | NSRect dstRect = NSMakeRect (x+shift_by, y, width, height); | 2932 | NSRect dstRect = NSMakeRect (x+shift_by, y, width, height); |
| 2957 | 2933 | ||
| 2958 | NSTRACE ("ns_shift_glyphs_for_insert"); | 2934 | NSTRACE ("ns_shift_glyphs_for_insert"); |
| 2959 | 2935 | ||
| 2960 | ns_copy_bits (f, srcRect, dstRect); | 2936 | /* This doesn't work now as we copy the "bits" before we've had a |
| 2937 | chance to actually draw any changes to the screen. This means in | ||
| 2938 | certain circumstances we end up with copies of the cursor all | ||
| 2939 | over the place. Just mark the area dirty so it is redrawn later. | ||
| 2940 | |||
| 2941 | FIXME: Work out how to do this properly. */ | ||
| 2942 | // ns_copy_bits (f, srcRect, dstRect); | ||
| 2943 | |||
| 2944 | [FRAME_NS_VIEW (f) setNeedsDisplayInRect:dstRect]; | ||
| 2961 | } | 2945 | } |
| 2962 | 2946 | ||
| 2963 | 2947 | ||
| @@ -3038,6 +3022,9 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 3038 | struct face *face = p->face; | 3022 | struct face *face = p->face; |
| 3039 | static EmacsImage **bimgs = NULL; | 3023 | static EmacsImage **bimgs = NULL; |
| 3040 | static int nBimgs = 0; | 3024 | static int nBimgs = 0; |
| 3025 | NSRect clearRect = NSZeroRect; | ||
| 3026 | NSRect imageRect = NSZeroRect; | ||
| 3027 | NSRect rowRect = ns_row_rect (w, row, ANY_AREA); | ||
| 3041 | 3028 | ||
| 3042 | NSTRACE_WHEN (NSTRACE_GROUP_FRINGE, "ns_draw_fringe_bitmap"); | 3029 | NSTRACE_WHEN (NSTRACE_GROUP_FRINGE, "ns_draw_fringe_bitmap"); |
| 3043 | NSTRACE_MSG ("which:%d cursor:%d overlay:%d width:%d height:%d period:%d", | 3030 | NSTRACE_MSG ("which:%d cursor:%d overlay:%d width:%d height:%d period:%d", |
| @@ -3052,25 +3039,40 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 3052 | nBimgs = max_used_fringe_bitmap; | 3039 | nBimgs = max_used_fringe_bitmap; |
| 3053 | } | 3040 | } |
| 3054 | 3041 | ||
| 3055 | /* Must clip because of partially visible lines. */ | 3042 | /* Work out the rectangle we will composite into. */ |
| 3056 | if (ns_clip_to_row (w, row, ANY_AREA, YES)) | 3043 | if (p->which) |
| 3044 | imageRect = NSMakeRect (p->x, p->y, p->wd, p->h); | ||
| 3045 | |||
| 3046 | /* Work out the rectangle we will need to clear. Because we're | ||
| 3047 | compositing rather than blitting, we need to clear the area under | ||
| 3048 | the image regardless of anything else. */ | ||
| 3049 | if (!p->overlay_p) | ||
| 3050 | { | ||
| 3051 | clearRect = NSMakeRect (p->bx, p->by, p->nx, p->ny); | ||
| 3052 | clearRect = NSUnionRect (clearRect, imageRect); | ||
| 3053 | } | ||
| 3054 | else | ||
| 3055 | { | ||
| 3056 | clearRect = imageRect; | ||
| 3057 | } | ||
| 3058 | |||
| 3059 | /* Handle partially visible rows. */ | ||
| 3060 | clearRect = NSIntersectionRect (clearRect, rowRect); | ||
| 3061 | |||
| 3062 | /* The visible portion of imageRect will always be contained within | ||
| 3063 | clearRect. */ | ||
| 3064 | if (ns_clip_to_rect (f, &clearRect, 1)) | ||
| 3057 | { | 3065 | { |
| 3058 | if (!p->overlay_p) | 3066 | if (! NSIsEmptyRect (clearRect)) |
| 3059 | { | 3067 | { |
| 3060 | int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny; | 3068 | NSTRACE_RECT ("clearRect", clearRect); |
| 3061 | 3069 | ||
| 3062 | if (bx >= 0 && nx > 0) | 3070 | [ns_lookup_indexed_color(face->background, f) set]; |
| 3063 | { | 3071 | NSRectFill (clearRect); |
| 3064 | NSRect r = NSMakeRect (bx, by, nx, ny); | ||
| 3065 | NSRectClip (r); | ||
| 3066 | [ns_lookup_indexed_color (face->background, f) set]; | ||
| 3067 | NSRectFill (r); | ||
| 3068 | } | ||
| 3069 | } | 3072 | } |
| 3070 | 3073 | ||
| 3071 | if (p->which) | 3074 | if (p->which) |
| 3072 | { | 3075 | { |
| 3073 | NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h); | ||
| 3074 | EmacsImage *img = bimgs[p->which - 1]; | 3076 | EmacsImage *img = bimgs[p->which - 1]; |
| 3075 | 3077 | ||
| 3076 | if (!img) | 3078 | if (!img) |
| @@ -3091,13 +3093,6 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 3091 | xfree (cbits); | 3093 | xfree (cbits); |
| 3092 | } | 3094 | } |
| 3093 | 3095 | ||
| 3094 | NSTRACE_RECT ("r", r); | ||
| 3095 | |||
| 3096 | NSRectClip (r); | ||
| 3097 | /* Since we composite the bitmap instead of just blitting it, we need | ||
| 3098 | to erase the whole background. */ | ||
| 3099 | [ns_lookup_indexed_color(face->background, f) set]; | ||
| 3100 | NSRectFill (r); | ||
| 3101 | 3096 | ||
| 3102 | { | 3097 | { |
| 3103 | NSColor *bm_color; | 3098 | NSColor *bm_color; |
| @@ -3117,7 +3112,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 3117 | 3112 | ||
| 3118 | NSTRACE_RECT ("fromRect", fromRect); | 3113 | NSTRACE_RECT ("fromRect", fromRect); |
| 3119 | 3114 | ||
| 3120 | [img drawInRect: r | 3115 | [img drawInRect: imageRect |
| 3121 | fromRect: fromRect | 3116 | fromRect: fromRect |
| 3122 | operation: NSCompositingOperationSourceOver | 3117 | operation: NSCompositingOperationSourceOver |
| 3123 | fraction: 1.0 | 3118 | fraction: 1.0 |
| @@ -3125,7 +3120,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 3125 | hints: nil]; | 3120 | hints: nil]; |
| 3126 | #else | 3121 | #else |
| 3127 | { | 3122 | { |
| 3128 | NSPoint pt = r.origin; | 3123 | NSPoint pt = imageRect.origin; |
| 3129 | pt.y += p->h; | 3124 | pt.y += p->h; |
| 3130 | [img compositeToPoint: pt operation: NSCompositingOperationSourceOver]; | 3125 | [img compositeToPoint: pt operation: NSCompositingOperationSourceOver]; |
| 3131 | } | 3126 | } |
| @@ -3215,7 +3210,9 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, | |||
| 3215 | r.size.width = w->phys_cursor_width; | 3210 | r.size.width = w->phys_cursor_width; |
| 3216 | 3211 | ||
| 3217 | /* Prevent the cursor from being drawn outside the text area. */ | 3212 | /* Prevent the cursor from being drawn outside the text area. */ |
| 3218 | if (ns_clip_to_row (w, glyph_row, TEXT_AREA, NO)) | 3213 | r = NSIntersectionRect (r, ns_row_rect (w, glyph_row, TEXT_AREA)); |
| 3214 | |||
| 3215 | if (ns_clip_to_rect (f, &r, 1)) | ||
| 3219 | { | 3216 | { |
| 3220 | face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id); | 3217 | face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id); |
| 3221 | if (face && NS_FACE_BACKGROUND (face) | 3218 | if (face && NS_FACE_BACKGROUND (face) |
| @@ -3255,11 +3252,18 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, | |||
| 3255 | NSRectFill (s); | 3252 | NSRectFill (s); |
| 3256 | break; | 3253 | break; |
| 3257 | } | 3254 | } |
| 3258 | ns_reset_clipping (f); | ||
| 3259 | 3255 | ||
| 3260 | /* draw the character under the cursor */ | 3256 | /* draw the character under the cursor */ |
| 3261 | if (cursor_type != NO_CURSOR) | 3257 | if (cursor_type != NO_CURSOR) |
| 3262 | draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); | 3258 | draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); |
| 3259 | |||
| 3260 | ns_reset_clipping (f); | ||
| 3261 | } | ||
| 3262 | else if (! redisplaying_p) | ||
| 3263 | { | ||
| 3264 | /* If this function is called outside redisplay, it probably | ||
| 3265 | means we need an immediate update. */ | ||
| 3266 | [FRAME_NS_VIEW (f) display]; | ||
| 3263 | } | 3267 | } |
| 3264 | } | 3268 | } |
| 3265 | 3269 | ||
| @@ -8165,6 +8169,9 @@ not_in_argv (NSString *arg) | |||
| 8165 | for (int i = 0 ; i < numRects ; i++) | 8169 | for (int i = 0 ; i < numRects ; i++) |
| 8166 | { | 8170 | { |
| 8167 | NSRect r = rectList[i]; | 8171 | NSRect r = rectList[i]; |
| 8172 | |||
| 8173 | NSTRACE_RECT ("r", r); | ||
| 8174 | |||
| 8168 | expose_frame (emacsframe, | 8175 | expose_frame (emacsframe, |
| 8169 | NSMinX (r), NSMinY (r), | 8176 | NSMinX (r), NSMinY (r), |
| 8170 | NSWidth (r), NSHeight (r)); | 8177 | NSWidth (r), NSHeight (r)); |
diff --git a/src/xdisp.c b/src/xdisp.c index fa7691cdd0f..a0113a05190 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -32360,7 +32360,14 @@ expose_window_tree (struct window *w, XRectangle *r) | |||
| 32360 | struct frame *f = XFRAME (w->frame); | 32360 | struct frame *f = XFRAME (w->frame); |
| 32361 | bool mouse_face_overwritten_p = false; | 32361 | bool mouse_face_overwritten_p = false; |
| 32362 | 32362 | ||
| 32363 | while (w && !FRAME_GARBAGED_P (f)) | 32363 | /* NS toolkits may have aleady modified the frame in expectation of |
| 32364 | a successful redraw, so don't bail out here if the frame is | ||
| 32365 | garbaged. */ | ||
| 32366 | while (w | ||
| 32367 | #if !defined (HAVE_NS) | ||
| 32368 | && !FRAME_GARBAGED_P (f) | ||
| 32369 | #endif | ||
| 32370 | ) | ||
| 32364 | { | 32371 | { |
| 32365 | mouse_face_overwritten_p | 32372 | mouse_face_overwritten_p |
| 32366 | |= (WINDOWP (w->contents) | 32373 | |= (WINDOWP (w->contents) |
| @@ -32388,12 +32395,16 @@ expose_frame (struct frame *f, int x, int y, int w, int h) | |||
| 32388 | 32395 | ||
| 32389 | TRACE ((stderr, "expose_frame ")); | 32396 | TRACE ((stderr, "expose_frame ")); |
| 32390 | 32397 | ||
| 32391 | /* No need to redraw if frame will be redrawn soon. */ | 32398 | #if !defined (HAVE_NS) |
| 32399 | /* No need to redraw if frame will be redrawn soon except under NS | ||
| 32400 | where the toolkit may have already modified the frame in | ||
| 32401 | expectation of us redrawing it. */ | ||
| 32392 | if (FRAME_GARBAGED_P (f)) | 32402 | if (FRAME_GARBAGED_P (f)) |
| 32393 | { | 32403 | { |
| 32394 | TRACE ((stderr, " garbaged\n")); | 32404 | TRACE ((stderr, " garbaged\n")); |
| 32395 | return; | 32405 | return; |
| 32396 | } | 32406 | } |
| 32407 | #endif | ||
| 32397 | 32408 | ||
| 32398 | /* If basic faces haven't been realized yet, there is no point in | 32409 | /* If basic faces haven't been realized yet, there is no point in |
| 32399 | trying to redraw anything. This can happen when we get an expose | 32410 | trying to redraw anything. This can happen when we get an expose |