aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlan Third2018-09-28 20:23:07 +0100
committerAlan Third2018-09-28 20:23:46 +0100
commit7946445962372c4255180af45cb7c857f1b0b5fa (patch)
tree069baad0433140d7ccdc166bb8551b588cdf4d7c /src
parent41fa88b99bebf7af62cdea0c0867b04e9b968db3 (diff)
downloademacs-7946445962372c4255180af45cb7c857f1b0b5fa.tar.gz
emacs-7946445962372c4255180af45cb7c857f1b0b5fa.zip
Make all NS drawing be done from drawRect
See bug#31904 and bug#32812. * src/nsterm.m (ns_update_begin): Don't lock focus, only clip if there is already a view focused. (ns_update_end): Don't mess with view focusing any more. (ns_focus): Only clip drawing if there is already a focused view, otherwise mark area dirty for later drawing. Renamed ns_clip_to_rect. All callers changed. (ns_unfocus): Don't unfocus the view any more. Renamed ns_reset_clipping. All callers changed. (ns_clip_to_row): Update to match ns_clip_to_rect. (ns_clear_frame): (ns_clear_frame_area): (ns_draw_fringe_bitmap): (ns_draw_window_cursor): (ns_draw_vertical_window_border): (ns_draw_window_divider): (ns_dumpglyphs_stretch): (ns_draw_glyph_string): Only draw if ns_focus or ns_clip_to_row return YES. (ns_copy_bits): Remove superfluous calls to ns_(un)focus. (ns_flush_display): New function.
Diffstat (limited to 'src')
-rw-r--r--src/nsterm.m767
1 files changed, 376 insertions, 391 deletions
diff --git a/src/nsterm.m b/src/nsterm.m
index 5ed71c9f8f1..954020dcde9 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -276,12 +276,7 @@ struct ns_display_info *x_display_list; /* Chain of existing displays */
276long context_menu_value = 0; 276long context_menu_value = 0;
277 277
278/* display update */ 278/* display update */
279static struct frame *ns_updating_frame;
280static NSView *focus_view = NULL;
281static int ns_window_num = 0; 279static int ns_window_num = 0;
282#ifdef NS_IMPL_GNUSTEP
283static NSRect uRect; // TODO: This is dead, remove it?
284#endif
285static BOOL gsaved = NO; 280static BOOL gsaved = NO;
286static BOOL ns_fake_keydown = NO; 281static BOOL ns_fake_keydown = NO;
287#ifdef NS_IMPL_COCOA 282#ifdef NS_IMPL_COCOA
@@ -1039,12 +1034,13 @@ ns_update_begin (struct frame *f)
1039 external (RIF) call; whole frame, called before update_window_begin 1034 external (RIF) call; whole frame, called before update_window_begin
1040 -------------------------------------------------------------------------- */ 1035 -------------------------------------------------------------------------- */
1041{ 1036{
1037#ifdef NS_IMPL_COCOA
1042 EmacsView *view = FRAME_NS_VIEW (f); 1038 EmacsView *view = FRAME_NS_VIEW (f);
1039
1043 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_begin"); 1040 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_begin");
1044 1041
1045 ns_update_auto_hide_menu_bar (); 1042 ns_update_auto_hide_menu_bar ();
1046 1043
1047#ifdef NS_IMPL_COCOA
1048 if ([view isFullscreen] && [view fsIsNative]) 1044 if ([view isFullscreen] && [view fsIsNative])
1049 { 1045 {
1050 // Fix reappearing tool bar in fullscreen for Mac OS X 10.7 1046 // Fix reappearing tool bar in fullscreen for Mac OS X 10.7
@@ -1053,36 +1049,29 @@ ns_update_begin (struct frame *f)
1053 if (! tbar_visible != ! [toolbar isVisible]) 1049 if (! tbar_visible != ! [toolbar isVisible])
1054 [toolbar setVisible: tbar_visible]; 1050 [toolbar setVisible: tbar_visible];
1055 } 1051 }
1056#endif
1057
1058 ns_updating_frame = f;
1059 [view lockFocus];
1060 1052
1061 /* drawRect may have been called for say the minibuffer, and then clip path 1053 /* drawRect may have been called for say the minibuffer, and then clip path
1062 is for the minibuffer. But the display engine may draw more because 1054 is for the minibuffer. But the display engine may draw more because
1063 we have set the frame as garbaged. So reset clip path to the whole 1055 we have set the frame as garbaged. So reset clip path to the whole
1064 view. */ 1056 view. */
1065#ifdef NS_IMPL_COCOA 1057 /* FIXME: I don't think we need to do this. */
1066 { 1058 if ([NSView focusView] == FRAME_NS_VIEW (f))
1067 NSBezierPath *bp; 1059 {
1068 NSRect r = [view frame]; 1060 NSBezierPath *bp;
1069 NSRect cr = [[view window] frame]; 1061 NSRect r = [view frame];
1070 /* If a large frame size is set, r may be larger than the window frame 1062 NSRect cr = [[view window] frame];
1071 before constrained. In that case don't change the clip path, as we 1063 /* If a large frame size is set, r may be larger than the window frame
1072 will clear in to the tool bar and title bar. */ 1064 before constrained. In that case don't change the clip path, as we
1073 if (r.size.height 1065 will clear in to the tool bar and title bar. */
1074 + FRAME_NS_TITLEBAR_HEIGHT (f) 1066 if (r.size.height
1075 + FRAME_TOOLBAR_HEIGHT (f) <= cr.size.height) 1067 + FRAME_NS_TITLEBAR_HEIGHT (f)
1076 { 1068 + FRAME_TOOLBAR_HEIGHT (f) <= cr.size.height)
1077 bp = [[NSBezierPath bezierPathWithRect: r] retain]; 1069 {
1078 [bp setClip]; 1070 bp = [[NSBezierPath bezierPathWithRect: r] retain];
1079 [bp release]; 1071 [bp setClip];
1080 } 1072 [bp release];
1081 } 1073 }
1082#endif 1074 }
1083
1084#ifdef NS_IMPL_GNUSTEP
1085 uRect = NSMakeRect (0, 0, 0, 0);
1086#endif 1075#endif
1087} 1076}
1088 1077
@@ -1164,99 +1153,66 @@ ns_update_end (struct frame *f)
1164 external (RIF) call; for whole frame, called after update_window_end 1153 external (RIF) call; for whole frame, called after update_window_end
1165 -------------------------------------------------------------------------- */ 1154 -------------------------------------------------------------------------- */
1166{ 1155{
1167 EmacsView *view = FRAME_NS_VIEW (f);
1168
1169 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_end"); 1156 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_end");
1170 1157
1171/* if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */ 1158/* if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */
1172 MOUSE_HL_INFO (f)->mouse_face_defer = 0; 1159 MOUSE_HL_INFO (f)->mouse_face_defer = 0;
1173
1174 block_input ();
1175
1176 [view unlockFocus];
1177 [[view window] flushWindow];
1178
1179 unblock_input ();
1180 ns_updating_frame = NULL;
1181} 1160}
1182 1161
1183static void 1162
1184ns_focus (struct frame *f, NSRect *r, int n) 1163static BOOL
1164ns_clip_to_rect (struct frame *f, NSRect *r, int n)
1185/* -------------------------------------------------------------------------- 1165/* --------------------------------------------------------------------------
1186 Internal: Focus on given frame. During small local updates this is used to 1166 Clip the drawing area to rectangle r in frame f. If drawing is not
1187 draw, however during large updates, ns_update_begin and ns_update_end are 1167 currently possible mark r as dirty and return NO, otherwise return
1188 called to wrap the whole thing, in which case these calls are stubbed out. 1168 YES.
1189 Except, on GNUstep, we accumulate the rectangle being drawn into, because
1190 the back end won't do this automatically, and will just end up flushing
1191 the entire window.
1192 -------------------------------------------------------------------------- */ 1169 -------------------------------------------------------------------------- */
1193{ 1170{
1194 NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_focus"); 1171 NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_clip_to_rect");
1195 if (r != NULL) 1172 if (r)
1196 { 1173 {
1197 NSTRACE_RECT ("r", *r); 1174 NSTRACE_RECT ("r", *r);
1198 }
1199 1175
1200 if (f != ns_updating_frame) 1176 if ([NSView focusView] == FRAME_NS_VIEW (f))
1201 {
1202 NSView *view = FRAME_NS_VIEW (f);
1203 if (view != focus_view)
1204 { 1177 {
1205 if (focus_view != NULL) 1178 [[NSGraphicsContext currentContext] saveGraphicsState];
1206 { 1179 if (n == 2)
1207 [focus_view unlockFocus]; 1180 NSRectClipList (r, 2);
1208 [[focus_view window] flushWindow]; 1181 else
1209/*debug_lock--; */ 1182 NSRectClip (*r);
1210 } 1183 gsaved = YES;
1211 1184
1212 if (view) 1185 return YES;
1213 [view lockFocus];
1214 focus_view = view;
1215/*if (view) debug_lock++; */
1216 } 1186 }
1217 }
1218
1219 /* clipping */
1220 if (r)
1221 {
1222 [[NSGraphicsContext currentContext] saveGraphicsState];
1223 if (n == 2)
1224 NSRectClipList (r, 2);
1225 else 1187 else
1226 NSRectClip (*r); 1188 {
1227 gsaved = YES; 1189 NSView *view = FRAME_NS_VIEW (f);
1190 int i;
1191 for (i = 0 ; i < n ; i++)
1192 [view setNeedsDisplayInRect:r[i]];
1193 }
1228 } 1194 }
1195
1196 return NO;
1229} 1197}
1230 1198
1231 1199
1232static void 1200static void
1233ns_unfocus (struct frame *f) 1201ns_reset_clipping (struct frame *f)
1234/* -------------------------------------------------------------------------- 1202/* Internal: Restore the previous graphics state, unsetting any
1235 Internal: Remove focus on given frame 1203 clipping areas. */
1236 -------------------------------------------------------------------------- */
1237{ 1204{
1238 NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_unfocus"); 1205 NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_reset_clipping");
1239 1206
1240 if (gsaved) 1207 if (gsaved)
1241 { 1208 {
1242 [[NSGraphicsContext currentContext] restoreGraphicsState]; 1209 [[NSGraphicsContext currentContext] restoreGraphicsState];
1243 gsaved = NO; 1210 gsaved = NO;
1244 } 1211 }
1245
1246 if (f != ns_updating_frame)
1247 {
1248 if (focus_view != NULL)
1249 {
1250 [focus_view unlockFocus];
1251 [[focus_view window] flushWindow];
1252 focus_view = NULL;
1253/*debug_lock--; */
1254 }
1255 }
1256} 1212}
1257 1213
1258 1214
1259static void 1215static BOOL
1260ns_clip_to_row (struct window *w, struct glyph_row *row, 1216ns_clip_to_row (struct window *w, struct glyph_row *row,
1261 enum glyph_row_area area, BOOL gc) 1217 enum glyph_row_area area, BOOL gc)
1262/* -------------------------------------------------------------------------- 1218/* --------------------------------------------------------------------------
@@ -1275,7 +1231,19 @@ ns_clip_to_row (struct window *w, struct glyph_row *row,
1275 clip_rect.size.width = window_width; 1231 clip_rect.size.width = window_width;
1276 clip_rect.size.height = row->visible_height; 1232 clip_rect.size.height = row->visible_height;
1277 1233
1278 ns_focus (f, &clip_rect, 1); 1234 return ns_clip_to_rect (f, &clip_rect, 1);
1235}
1236
1237
1238static void
1239ns_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 ();
1279} 1247}
1280 1248
1281 1249
@@ -2699,14 +2667,16 @@ ns_clear_frame (struct frame *f)
2699 r = [view bounds]; 2667 r = [view bounds];
2700 2668
2701 block_input (); 2669 block_input ();
2702 ns_focus (f, &r, 1); 2670 if (ns_clip_to_rect (f, &r, 1))
2703 [ns_lookup_indexed_color (NS_FACE_BACKGROUND 2671 {
2704 (FACE_FROM_ID (f, DEFAULT_FACE_ID)), f) set]; 2672 [ns_lookup_indexed_color (NS_FACE_BACKGROUND
2705 NSRectFill (r); 2673 (FACE_FROM_ID (f, DEFAULT_FACE_ID)), f) set];
2706 ns_unfocus (f); 2674 NSRectFill (r);
2707 2675 ns_reset_clipping (f);
2708 /* as of 2006/11 or so this is now needed */ 2676
2709 ns_redraw_scroll_bars (f); 2677 /* as of 2006/11 or so this is now needed */
2678 ns_redraw_scroll_bars (f);
2679 }
2710 unblock_input (); 2680 unblock_input ();
2711} 2681}
2712 2682
@@ -2727,13 +2697,14 @@ ns_clear_frame_area (struct frame *f, int x, int y, int width, int height)
2727 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_clear_frame_area"); 2697 NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_clear_frame_area");
2728 2698
2729 r = NSIntersectionRect (r, [view frame]); 2699 r = NSIntersectionRect (r, [view frame]);
2730 ns_focus (f, &r, 1); 2700 if (ns_clip_to_rect (f, &r, 1))
2731 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set]; 2701 {
2702 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
2732 2703
2733 NSRectFill (r); 2704 NSRectFill (r);
2734 2705
2735 ns_unfocus (f); 2706 ns_reset_clipping (f);
2736 return; 2707 }
2737} 2708}
2738 2709
2739static void 2710static void
@@ -2745,11 +2716,11 @@ ns_copy_bits (struct frame *f, NSRect src, NSRect dest)
2745 { 2716 {
2746 hide_bell(); // Ensure the bell image isn't scrolled. 2717 hide_bell(); // Ensure the bell image isn't scrolled.
2747 2718
2748 ns_focus (f, &dest, 1); 2719 /* 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. */
2749 [FRAME_NS_VIEW (f) scrollRect: src 2721 [FRAME_NS_VIEW (f) scrollRect: src
2750 by: NSMakeSize (dest.origin.x - src.origin.x, 2722 by: NSMakeSize (dest.origin.x - src.origin.x,
2751 dest.origin.y - src.origin.y)]; 2723 dest.origin.y - src.origin.y)];
2752 ns_unfocus (f);
2753 } 2724 }
2754} 2725}
2755 2726
@@ -2960,85 +2931,86 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2960 } 2931 }
2961 2932
2962 /* Must clip because of partially visible lines. */ 2933 /* Must clip because of partially visible lines. */
2963 ns_clip_to_row (w, row, ANY_AREA, YES); 2934 if (ns_clip_to_row (w, row, ANY_AREA, YES))
2964
2965 if (!p->overlay_p)
2966 { 2935 {
2967 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny; 2936 if (!p->overlay_p)
2968
2969 if (bx >= 0 && nx > 0)
2970 { 2937 {
2971 NSRect r = NSMakeRect (bx, by, nx, ny); 2938 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2972 NSRectClip (r);
2973 [ns_lookup_indexed_color (face->background, f) set];
2974 NSRectFill (r);
2975 }
2976 }
2977 2939
2978 if (p->which) 2940 if (bx >= 0 && nx > 0)
2979 { 2941 {
2980 NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h); 2942 NSRect r = NSMakeRect (bx, by, nx, ny);
2981 EmacsImage *img = bimgs[p->which - 1]; 2943 NSRectClip (r);
2982 2944 [ns_lookup_indexed_color (face->background, f) set];
2983 if (!img) 2945 NSRectFill (r);
2984 { 2946 }
2985 // Note: For "periodic" images, allocate one EmacsImage for
2986 // the base image, and use it for all dh:s.
2987 unsigned short *bits = p->bits;
2988 int full_height = p->h + p->dh;
2989 int i;
2990 unsigned char *cbits = xmalloc (full_height);
2991
2992 for (i = 0; i < full_height; i++)
2993 cbits[i] = bits[i];
2994 img = [[EmacsImage alloc] initFromXBM: cbits width: 8
2995 height: full_height
2996 fg: 0 bg: 0];
2997 bimgs[p->which - 1] = img;
2998 xfree (cbits);
2999 } 2947 }
3000 2948
3001 NSTRACE_RECT ("r", r); 2949 if (p->which)
2950 {
2951 NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h);
2952 EmacsImage *img = bimgs[p->which - 1];
3002 2953
3003 NSRectClip (r); 2954 if (!img)
3004 /* Since we composite the bitmap instead of just blitting it, we need 2955 {
3005 to erase the whole background. */ 2956 // Note: For "periodic" images, allocate one EmacsImage for
3006 [ns_lookup_indexed_color(face->background, f) set]; 2957 // the base image, and use it for all dh:s.
3007 NSRectFill (r); 2958 unsigned short *bits = p->bits;
2959 int full_height = p->h + p->dh;
2960 int i;
2961 unsigned char *cbits = xmalloc (full_height);
2962
2963 for (i = 0; i < full_height; i++)
2964 cbits[i] = bits[i];
2965 img = [[EmacsImage alloc] initFromXBM: cbits width: 8
2966 height: full_height
2967 fg: 0 bg: 0];
2968 bimgs[p->which - 1] = img;
2969 xfree (cbits);
2970 }
3008 2971
3009 { 2972 NSTRACE_RECT ("r", r);
3010 NSColor *bm_color;
3011 if (!p->cursor_p)
3012 bm_color = ns_lookup_indexed_color(face->foreground, f);
3013 else if (p->overlay_p)
3014 bm_color = ns_lookup_indexed_color(face->background, f);
3015 else
3016 bm_color = f->output_data.ns->cursor_color;
3017 [img setXBMColor: bm_color];
3018 }
3019 2973
3020#ifdef NS_IMPL_COCOA 2974 NSRectClip (r);
3021 // Note: For periodic images, the full image height is "h + hd". 2975 /* Since we composite the bitmap instead of just blitting it, we need
3022 // By using the height h, a suitable part of the image is used. 2976 to erase the whole background. */
3023 NSRect fromRect = NSMakeRect(0, 0, p->wd, p->h); 2977 [ns_lookup_indexed_color(face->background, f) set];
2978 NSRectFill (r);
3024 2979
3025 NSTRACE_RECT ("fromRect", fromRect); 2980 {
2981 NSColor *bm_color;
2982 if (!p->cursor_p)
2983 bm_color = ns_lookup_indexed_color(face->foreground, f);
2984 else if (p->overlay_p)
2985 bm_color = ns_lookup_indexed_color(face->background, f);
2986 else
2987 bm_color = f->output_data.ns->cursor_color;
2988 [img setXBMColor: bm_color];
2989 }
3026 2990
3027 [img drawInRect: r 2991#ifdef NS_IMPL_COCOA
3028 fromRect: fromRect 2992 // Note: For periodic images, the full image height is "h + hd".
3029 operation: NSCompositingOperationSourceOver 2993 // By using the height h, a suitable part of the image is used.
3030 fraction: 1.0 2994 NSRect fromRect = NSMakeRect(0, 0, p->wd, p->h);
3031 respectFlipped: YES 2995
3032 hints: nil]; 2996 NSTRACE_RECT ("fromRect", fromRect);
2997
2998 [img drawInRect: r
2999 fromRect: fromRect
3000 operation: NSCompositingOperationSourceOver
3001 fraction: 1.0
3002 respectFlipped: YES
3003 hints: nil];
3033#else 3004#else
3034 { 3005 {
3035 NSPoint pt = r.origin; 3006 NSPoint pt = r.origin;
3036 pt.y += p->h; 3007 pt.y += p->h;
3037 [img compositeToPoint: pt operation: NSCompositingOperationSourceOver]; 3008 [img compositeToPoint: pt operation: NSCompositingOperationSourceOver];
3038 } 3009 }
3039#endif 3010#endif
3011 }
3012 ns_reset_clipping (f);
3040 } 3013 }
3041 ns_unfocus (f);
3042} 3014}
3043 3015
3044 3016
@@ -3120,67 +3092,66 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
3120 r.size.height = h; 3092 r.size.height = h;
3121 r.size.width = w->phys_cursor_width; 3093 r.size.width = w->phys_cursor_width;
3122 3094
3123 /* Prevent the cursor from being drawn outside the text area. */ 3095 /* Prevent the cursor from being drawn outside the text area. */
3124 ns_clip_to_row (w, glyph_row, TEXT_AREA, NO); /* do ns_focus(f, &r, 1); if remove */ 3096 if (ns_clip_to_row (w, glyph_row, TEXT_AREA, NO))
3125
3126
3127 face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id);
3128 if (face && NS_FACE_BACKGROUND (face)
3129 == ns_index_color (FRAME_CURSOR_COLOR (f), f))
3130 { 3097 {
3131 [ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), f) set]; 3098 face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id);
3132 hollow_color = FRAME_CURSOR_COLOR (f); 3099 if (face && NS_FACE_BACKGROUND (face)
3133 } 3100 == ns_index_color (FRAME_CURSOR_COLOR (f), f))
3134 else 3101 {
3135 [FRAME_CURSOR_COLOR (f) set]; 3102 [ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), f) set];
3103 hollow_color = FRAME_CURSOR_COLOR (f);
3104 }
3105 else
3106 [FRAME_CURSOR_COLOR (f) set];
3136 3107
3137#ifdef NS_IMPL_COCOA 3108#ifdef NS_IMPL_COCOA
3138 /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph 3109 /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph
3139 atomic. Cleaner ways of doing this should be investigated. 3110 atomic. Cleaner ways of doing this should be investigated.
3140 One way would be to set a global variable DRAWING_CURSOR 3111 One way would be to set a global variable DRAWING_CURSOR
3141 when making the call to draw_phys..(), don't focus in that 3112 when making the call to draw_phys..(), don't focus in that
3142 case, then move the ns_unfocus() here after that call. */ 3113 case, then move the ns_reset_clipping() here after that call. */
3143 NSDisableScreenUpdates (); 3114 NSDisableScreenUpdates ();
3144#endif 3115#endif
3145 3116
3146 switch (cursor_type) 3117 switch (cursor_type)
3147 { 3118 {
3148 case DEFAULT_CURSOR: 3119 case DEFAULT_CURSOR:
3149 case NO_CURSOR: 3120 case NO_CURSOR:
3150 break; 3121 break;
3151 case FILLED_BOX_CURSOR: 3122 case FILLED_BOX_CURSOR:
3152 NSRectFill (r); 3123 NSRectFill (r);
3153 break; 3124 break;
3154 case HOLLOW_BOX_CURSOR: 3125 case HOLLOW_BOX_CURSOR:
3155 NSRectFill (r); 3126 NSRectFill (r);
3156 [hollow_color set]; 3127 [hollow_color set];
3157 NSRectFill (NSInsetRect (r, 1, 1)); 3128 NSRectFill (NSInsetRect (r, 1, 1));
3158 [FRAME_CURSOR_COLOR (f) set]; 3129 [FRAME_CURSOR_COLOR (f) set];
3159 break; 3130 break;
3160 case HBAR_CURSOR: 3131 case HBAR_CURSOR:
3161 NSRectFill (r); 3132 NSRectFill (r);
3162 break; 3133 break;
3163 case BAR_CURSOR: 3134 case BAR_CURSOR:
3164 s = r; 3135 s = r;
3165 /* If the character under cursor is R2L, draw the bar cursor 3136 /* If the character under cursor is R2L, draw the bar cursor
3166 on the right of its glyph, rather than on the left. */ 3137 on the right of its glyph, rather than on the left. */
3167 cursor_glyph = get_phys_cursor_glyph (w); 3138 cursor_glyph = get_phys_cursor_glyph (w);
3168 if ((cursor_glyph->resolved_level & 1) != 0) 3139 if ((cursor_glyph->resolved_level & 1) != 0)
3169 s.origin.x += cursor_glyph->pixel_width - s.size.width; 3140 s.origin.x += cursor_glyph->pixel_width - s.size.width;
3170 3141
3171 NSRectFill (s); 3142 NSRectFill (s);
3172 break; 3143 break;
3173 } 3144 }
3174 ns_unfocus (f); 3145 ns_reset_clipping (f);
3175 3146
3176 /* draw the character under the cursor */ 3147 /* draw the character under the cursor */
3177 if (cursor_type != NO_CURSOR) 3148 if (cursor_type != NO_CURSOR)
3178 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); 3149 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
3179 3150
3180#ifdef NS_IMPL_COCOA 3151#ifdef NS_IMPL_COCOA
3181 NSEnableScreenUpdates (); 3152 NSEnableScreenUpdates ();
3182#endif 3153#endif
3183 3154 }
3184} 3155}
3185 3156
3186 3157
@@ -3198,12 +3169,14 @@ ns_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
3198 3169
3199 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID); 3170 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
3200 3171
3201 ns_focus (f, &r, 1); 3172 if (ns_clip_to_rect (f, &r, 1))
3202 if (face) 3173 {
3203 [ns_lookup_indexed_color(face->foreground, f) set]; 3174 if (face)
3175 [ns_lookup_indexed_color(face->foreground, f) set];
3204 3176
3205 NSRectFill(r); 3177 NSRectFill(r);
3206 ns_unfocus (f); 3178 ns_reset_clipping (f);
3179 }
3207} 3180}
3208 3181
3209 3182
@@ -3230,39 +3203,40 @@ ns_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
3230 3203
3231 NSTRACE ("ns_draw_window_divider"); 3204 NSTRACE ("ns_draw_window_divider");
3232 3205
3233 ns_focus (f, &divider, 1); 3206 if (ns_clip_to_rect (f, &divider, 1))
3234
3235 if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
3236 /* A vertical divider, at least three pixels wide: Draw first and
3237 last pixels differently. */
3238 { 3207 {
3239 [ns_lookup_indexed_color(color_first, f) set]; 3208 if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
3240 NSRectFill(NSMakeRect (x0, y0, 1, y1 - y0)); 3209 /* A vertical divider, at least three pixels wide: Draw first and
3241 [ns_lookup_indexed_color(color, f) set]; 3210 last pixels differently. */
3242 NSRectFill(NSMakeRect (x0 + 1, y0, x1 - x0 - 2, y1 - y0)); 3211 {
3243 [ns_lookup_indexed_color(color_last, f) set]; 3212 [ns_lookup_indexed_color(color_first, f) set];
3244 NSRectFill(NSMakeRect (x1 - 1, y0, 1, y1 - y0)); 3213 NSRectFill(NSMakeRect (x0, y0, 1, y1 - y0));
3245 } 3214 [ns_lookup_indexed_color(color, f) set];
3246 else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3)) 3215 NSRectFill(NSMakeRect (x0 + 1, y0, x1 - x0 - 2, y1 - y0));
3247 /* A horizontal divider, at least three pixels high: Draw first and 3216 [ns_lookup_indexed_color(color_last, f) set];
3248 last pixels differently. */ 3217 NSRectFill(NSMakeRect (x1 - 1, y0, 1, y1 - y0));
3249 { 3218 }
3250 [ns_lookup_indexed_color(color_first, f) set]; 3219 else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
3251 NSRectFill(NSMakeRect (x0, y0, x1 - x0, 1)); 3220 /* A horizontal divider, at least three pixels high: Draw first and
3252 [ns_lookup_indexed_color(color, f) set]; 3221 last pixels differently. */
3253 NSRectFill(NSMakeRect (x0, y0 + 1, x1 - x0, y1 - y0 - 2)); 3222 {
3254 [ns_lookup_indexed_color(color_last, f) set]; 3223 [ns_lookup_indexed_color(color_first, f) set];
3255 NSRectFill(NSMakeRect (x0, y1 - 1, x1 - x0, 1)); 3224 NSRectFill(NSMakeRect (x0, y0, x1 - x0, 1));
3256 } 3225 [ns_lookup_indexed_color(color, f) set];
3257 else 3226 NSRectFill(NSMakeRect (x0, y0 + 1, x1 - x0, y1 - y0 - 2));
3258 { 3227 [ns_lookup_indexed_color(color_last, f) set];
3259 /* In any other case do not draw the first and last pixels 3228 NSRectFill(NSMakeRect (x0, y1 - 1, x1 - x0, 1));
3260 differently. */ 3229 }
3261 [ns_lookup_indexed_color(color, f) set]; 3230 else
3262 NSRectFill(divider); 3231 {
3263 } 3232 /* In any other case do not draw the first and last pixels
3233 differently. */
3234 [ns_lookup_indexed_color(color, f) set];
3235 NSRectFill(divider);
3236 }
3264 3237
3265 ns_unfocus (f); 3238 ns_reset_clipping (f);
3239 }
3266} 3240}
3267 3241
3268static void 3242static void
@@ -3846,83 +3820,84 @@ ns_dumpglyphs_stretch (struct glyph_string *s)
3846 n = ns_get_glyph_string_clip_rect (s, r); 3820 n = ns_get_glyph_string_clip_rect (s, r);
3847 *r = NSMakeRect (s->x, s->y, s->background_width, s->height); 3821 *r = NSMakeRect (s->x, s->y, s->background_width, s->height);
3848 3822
3849 ns_focus (s->f, r, n); 3823 if (ns_clip_to_rect (s->f, r, n))
3850
3851 if (s->hl == DRAW_MOUSE_FACE)
3852 {
3853 face = FACE_FROM_ID_OR_NULL (s->f,
3854 MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3855 if (!face)
3856 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3857 }
3858 else
3859 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
3860
3861 bgCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
3862 fgCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
3863
3864 for (i = 0; i < n; ++i)
3865 { 3824 {
3866 if (!s->row->full_width_p) 3825 if (s->hl == DRAW_MOUSE_FACE)
3867 { 3826 {
3868 int overrun, leftoverrun; 3827 face = FACE_FROM_ID_OR_NULL (s->f,
3869 3828 MOUSE_HL_INFO (s->f)->mouse_face_face_id);
3870 /* truncate to avoid overwriting fringe and/or scrollbar */ 3829 if (!face)
3871 overrun = max (0, (s->x + s->background_width) 3830 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3872 - (WINDOW_BOX_RIGHT_EDGE_X (s->w)
3873 - WINDOW_RIGHT_FRINGE_WIDTH (s->w)));
3874 r[i].size.width -= overrun;
3875
3876 /* truncate to avoid overwriting to left of the window box */
3877 leftoverrun = (WINDOW_BOX_LEFT_EDGE_X (s->w)
3878 + WINDOW_LEFT_FRINGE_WIDTH (s->w)) - s->x;
3879
3880 if (leftoverrun > 0)
3881 {
3882 r[i].origin.x += leftoverrun;
3883 r[i].size.width -= leftoverrun;
3884 }
3885
3886 /* XXX: Try to work between problem where a stretch glyph on
3887 a partially-visible bottom row will clear part of the
3888 modeline, and another where list-buffers headers and similar
3889 rows erroneously have visible_height set to 0. Not sure
3890 where this is coming from as other terms seem not to show. */
3891 r[i].size.height = min (s->height, s->row->visible_height);
3892 } 3831 }
3832 else
3833 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
3893 3834
3894 [bgCol set]; 3835 bgCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
3836 fgCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
3895 3837
3896 /* NOTE: under NS this is NOT used to draw cursors, but we must avoid 3838 for (i = 0; i < n; ++i)
3897 overwriting cursor (usually when cursor on a tab) */
3898 if (s->hl == DRAW_CURSOR)
3899 { 3839 {
3900 CGFloat x, width; 3840 if (!s->row->full_width_p)
3841 {
3842 int overrun, leftoverrun;
3843
3844 /* truncate to avoid overwriting fringe and/or scrollbar */
3845 overrun = max (0, (s->x + s->background_width)
3846 - (WINDOW_BOX_RIGHT_EDGE_X (s->w)
3847 - WINDOW_RIGHT_FRINGE_WIDTH (s->w)));
3848 r[i].size.width -= overrun;
3849
3850 /* truncate to avoid overwriting to left of the window box */
3851 leftoverrun = (WINDOW_BOX_LEFT_EDGE_X (s->w)
3852 + WINDOW_LEFT_FRINGE_WIDTH (s->w)) - s->x;
3853
3854 if (leftoverrun > 0)
3855 {
3856 r[i].origin.x += leftoverrun;
3857 r[i].size.width -= leftoverrun;
3858 }
3859
3860 /* XXX: Try to work between problem where a stretch glyph on
3861 a partially-visible bottom row will clear part of the
3862 modeline, and another where list-buffers headers and similar
3863 rows erroneously have visible_height set to 0. Not sure
3864 where this is coming from as other terms seem not to show. */
3865 r[i].size.height = min (s->height, s->row->visible_height);
3866 }
3867
3868 [bgCol set];
3869
3870 /* NOTE: under NS this is NOT used to draw cursors, but we must avoid
3871 overwriting cursor (usually when cursor on a tab). */
3872 if (s->hl == DRAW_CURSOR)
3873 {
3874 CGFloat x, width;
3901 3875
3902 x = r[i].origin.x; 3876 x = r[i].origin.x;
3903 width = s->w->phys_cursor_width; 3877 width = s->w->phys_cursor_width;
3904 r[i].size.width -= width; 3878 r[i].size.width -= width;
3905 r[i].origin.x += width; 3879 r[i].origin.x += width;
3906 3880
3907 NSRectFill (r[i]); 3881 NSRectFill (r[i]);
3908 3882
3909 /* Draw overlining, etc. on the cursor. */ 3883 /* Draw overlining, etc. on the cursor. */
3910 if (s->w->phys_cursor_type == FILLED_BOX_CURSOR) 3884 if (s->w->phys_cursor_type == FILLED_BOX_CURSOR)
3911 ns_draw_text_decoration (s, face, bgCol, width, x); 3885 ns_draw_text_decoration (s, face, bgCol, width, x);
3886 else
3887 ns_draw_text_decoration (s, face, fgCol, width, x);
3888 }
3912 else 3889 else
3913 ns_draw_text_decoration (s, face, fgCol, width, x); 3890 {
3914 } 3891 NSRectFill (r[i]);
3915 else 3892 }
3916 {
3917 NSRectFill (r[i]);
3918 }
3919 3893
3920 /* Draw overlining, etc. on the stretch glyph (or the part 3894 /* Draw overlining, etc. on the stretch glyph (or the part
3921 of the stretch glyph after the cursor). */ 3895 of the stretch glyph after the cursor). */
3922 ns_draw_text_decoration (s, face, fgCol, r[i].size.width, 3896 ns_draw_text_decoration (s, face, fgCol, r[i].size.width,
3923 r[i].origin.x); 3897 r[i].origin.x);
3898 }
3899 ns_reset_clipping (s->f);
3924 } 3900 }
3925 ns_unfocus (s->f);
3926 s->background_filled_p = 1; 3901 s->background_filled_p = 1;
3927 } 3902 }
3928} 3903}
@@ -4072,9 +4047,11 @@ ns_draw_glyph_string (struct glyph_string *s)
4072 if (next->first_glyph->type != STRETCH_GLYPH) 4047 if (next->first_glyph->type != STRETCH_GLYPH)
4073 { 4048 {
4074 n = ns_get_glyph_string_clip_rect (s->next, r); 4049 n = ns_get_glyph_string_clip_rect (s->next, r);
4075 ns_focus (s->f, r, n); 4050 if (ns_clip_to_rect (s->f, r, n))
4076 ns_maybe_dumpglyphs_background (s->next, 1); 4051 {
4077 ns_unfocus (s->f); 4052 ns_maybe_dumpglyphs_background (s->next, 1);
4053 ns_reset_clipping (s->f);
4054 }
4078 } 4055 }
4079 else 4056 else
4080 { 4057 {
@@ -4089,10 +4066,12 @@ ns_draw_glyph_string (struct glyph_string *s)
4089 || s->first_glyph->type == COMPOSITE_GLYPH)) 4066 || s->first_glyph->type == COMPOSITE_GLYPH))
4090 { 4067 {
4091 n = ns_get_glyph_string_clip_rect (s, r); 4068 n = ns_get_glyph_string_clip_rect (s, r);
4092 ns_focus (s->f, r, n); 4069 if (ns_clip_to_rect (s->f, r, n))
4093 ns_maybe_dumpglyphs_background (s, 1); 4070 {
4094 ns_dumpglyphs_box_or_relief (s); 4071 ns_maybe_dumpglyphs_background (s, 1);
4095 ns_unfocus (s->f); 4072 ns_dumpglyphs_box_or_relief (s);
4073 ns_reset_clipping (s->f);
4074 }
4096 box_drawn_p = 1; 4075 box_drawn_p = 1;
4097 } 4076 }
4098 4077
@@ -4101,9 +4080,11 @@ ns_draw_glyph_string (struct glyph_string *s)
4101 4080
4102 case IMAGE_GLYPH: 4081 case IMAGE_GLYPH:
4103 n = ns_get_glyph_string_clip_rect (s, r); 4082 n = ns_get_glyph_string_clip_rect (s, r);
4104 ns_focus (s->f, r, n); 4083 if (ns_clip_to_rect (s->f, r, n))
4105 ns_dumpglyphs_image (s, r[0]); 4084 {
4106 ns_unfocus (s->f); 4085 ns_dumpglyphs_image (s, r[0]);
4086 ns_reset_clipping (s->f);
4087 }
4107 break; 4088 break;
4108 4089
4109 case STRETCH_GLYPH: 4090 case STRETCH_GLYPH:
@@ -4113,66 +4094,68 @@ ns_draw_glyph_string (struct glyph_string *s)
4113 case CHAR_GLYPH: 4094 case CHAR_GLYPH:
4114 case COMPOSITE_GLYPH: 4095 case COMPOSITE_GLYPH:
4115 n = ns_get_glyph_string_clip_rect (s, r); 4096 n = ns_get_glyph_string_clip_rect (s, r);
4116 ns_focus (s->f, r, n); 4097 if (ns_clip_to_rect (s->f, r, n))
4098 {
4099 if (s->for_overlaps || (s->cmp_from > 0
4100 && ! s->first_glyph->u.cmp.automatic))
4101 s->background_filled_p = 1;
4102 else
4103 ns_maybe_dumpglyphs_background
4104 (s, s->first_glyph->type == COMPOSITE_GLYPH);
4117 4105
4118 if (s->for_overlaps || (s->cmp_from > 0 4106 if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
4119 && ! s->first_glyph->u.cmp.automatic)) 4107 {
4120 s->background_filled_p = 1; 4108 unsigned long tmp = NS_FACE_BACKGROUND (s->face);
4121 else 4109 NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
4122 ns_maybe_dumpglyphs_background 4110 NS_FACE_FOREGROUND (s->face) = tmp;
4123 (s, s->first_glyph->type == COMPOSITE_GLYPH); 4111 }
4124 4112
4125 if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR) 4113 {
4126 { 4114 BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH;
4127 unsigned long tmp = NS_FACE_BACKGROUND (s->face);
4128 NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
4129 NS_FACE_FOREGROUND (s->face) = tmp;
4130 }
4131 4115
4132 { 4116 if (isComposite)
4133 BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH; 4117 ns_draw_composite_glyph_string_foreground (s);
4118 else
4119 ns_draw_glyph_string_foreground (s);
4120 }
4134 4121
4135 if (isComposite) 4122 {
4136 ns_draw_composite_glyph_string_foreground (s); 4123 NSColor *col = (NS_FACE_FOREGROUND (s->face) != 0
4137 else 4124 ? ns_lookup_indexed_color (NS_FACE_FOREGROUND (s->face),
4138 ns_draw_glyph_string_foreground (s); 4125 s->f)
4139 } 4126 : FRAME_FOREGROUND_COLOR (s->f));
4127 [col set];
4128
4129 /* Draw underline, overline, strike-through. */
4130 ns_draw_text_decoration (s, s->face, col, s->width, s->x);
4131 }
4140 4132
4141 { 4133 if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
4142 NSColor *col = (NS_FACE_FOREGROUND (s->face) != 0 4134 {
4143 ? ns_lookup_indexed_color (NS_FACE_FOREGROUND (s->face), 4135 unsigned long tmp = NS_FACE_BACKGROUND (s->face);
4144 s->f) 4136 NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
4145 : FRAME_FOREGROUND_COLOR (s->f)); 4137 NS_FACE_FOREGROUND (s->face) = tmp;
4146 [col set]; 4138 }
4147
4148 /* Draw underline, overline, strike-through. */
4149 ns_draw_text_decoration (s, s->face, col, s->width, s->x);
4150 }
4151 4139
4152 if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR) 4140 ns_reset_clipping (s->f);
4153 {
4154 unsigned long tmp = NS_FACE_BACKGROUND (s->face);
4155 NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
4156 NS_FACE_FOREGROUND (s->face) = tmp;
4157 } 4141 }
4158
4159 ns_unfocus (s->f);
4160 break; 4142 break;
4161 4143
4162 case GLYPHLESS_GLYPH: 4144 case GLYPHLESS_GLYPH:
4163 n = ns_get_glyph_string_clip_rect (s, r); 4145 n = ns_get_glyph_string_clip_rect (s, r);
4164 ns_focus (s->f, r, n); 4146 if (ns_clip_to_rect (s->f, r, n))
4165 4147 {
4166 if (s->for_overlaps || (s->cmp_from > 0 4148 if (s->for_overlaps || (s->cmp_from > 0
4167 && ! s->first_glyph->u.cmp.automatic)) 4149 && ! s->first_glyph->u.cmp.automatic))
4168 s->background_filled_p = 1; 4150 s->background_filled_p = 1;
4169 else 4151 else
4170 ns_maybe_dumpglyphs_background 4152 ns_maybe_dumpglyphs_background
4171 (s, s->first_glyph->type == COMPOSITE_GLYPH); 4153 (s, s->first_glyph->type == COMPOSITE_GLYPH);
4172 /* ... */ 4154 /* ... */
4173 /* Not yet implemented. */ 4155 /* Not yet implemented. */
4174 /* ... */ 4156 /* ... */
4175 ns_unfocus (s->f); 4157 ns_reset_clipping (s->f);
4158 }
4176 break; 4159 break;
4177 4160
4178 default: 4161 default:
@@ -4183,9 +4166,11 @@ ns_draw_glyph_string (struct glyph_string *s)
4183 if (!s->for_overlaps && !box_drawn_p && s->face->box != FACE_NO_BOX) 4166 if (!s->for_overlaps && !box_drawn_p && s->face->box != FACE_NO_BOX)
4184 { 4167 {
4185 n = ns_get_glyph_string_clip_rect (s, r); 4168 n = ns_get_glyph_string_clip_rect (s, r);
4186 ns_focus (s->f, r, n); 4169 if (ns_clip_to_rect (s->f, r, n))
4187 ns_dumpglyphs_box_or_relief (s); 4170 {
4188 ns_unfocus (s->f); 4171 ns_dumpglyphs_box_or_relief (s);
4172 ns_reset_clipping (s->f);
4173 }
4189 } 4174 }
4190 4175
4191 s->num_clips = 0; 4176 s->num_clips = 0;
@@ -4991,7 +4976,7 @@ static struct redisplay_interface ns_redisplay_interface =
4991 ns_after_update_window_line, 4976 ns_after_update_window_line,
4992 ns_update_window_begin, 4977 ns_update_window_begin,
4993 ns_update_window_end, 4978 ns_update_window_end,
4994 0, /* flush_display */ 4979 ns_flush_display, /* flush_display */
4995 x_clear_window_mouse_face, 4980 x_clear_window_mouse_face,
4996 x_get_glyph_overhangs, 4981 x_get_glyph_overhangs,
4997 x_fix_overlapping_area, 4982 x_fix_overlapping_area,