From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Alan Third Newsgroups: gmane.emacs.bugs Subject: bug#31904: scatch/ns-drawing Date: Sat, 18 Aug 2018 15:02:33 +0100 Message-ID: <20180818140233.GA63685@breton.holly.idiocy.org> References: <75680C09-827A-4AB3-A930-F132AE8463A1@zentrope.com> <5C8BCF98-F8C6-465F-99C0-728F25A47982@zentrope.com> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="Nq2Wo0NMKNjxTN9z" Content-Transfer-Encoding: 8bit X-Trace: blaine.gmane.org 1534600876 26017 195.159.176.226 (18 Aug 2018 14:01:16 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Sat, 18 Aug 2018 14:01:16 +0000 (UTC) User-Agent: Mutt/1.10.0 (2018-05-17) Cc: 31904@debbugs.gnu.org To: "zentrope@fastmail.fm" Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sat Aug 18 16:01:11 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fr1mx-0006f4-8V for geb-bug-gnu-emacs@m.gmane.org; Sat, 18 Aug 2018 16:01:11 +0200 Original-Received: from localhost ([::1]:39059 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fr1p3-0003Wv-Oa for geb-bug-gnu-emacs@m.gmane.org; Sat, 18 Aug 2018 10:03:21 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:45940) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fr1op-0003WN-0A for bug-gnu-emacs@gnu.org; Sat, 18 Aug 2018 10:03:11 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fr1ol-0001iB-2Q for bug-gnu-emacs@gnu.org; Sat, 18 Aug 2018 10:03:06 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:49164) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fr1ok-0001hf-PP for bug-gnu-emacs@gnu.org; Sat, 18 Aug 2018 10:03:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1fr1ok-0005sZ-EE for bug-gnu-emacs@gnu.org; Sat, 18 Aug 2018 10:03:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Alan Third Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 18 Aug 2018 14:03:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 31904 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 31904-submit@debbugs.gnu.org id=B31904.153460096822542 (code B ref 31904); Sat, 18 Aug 2018 14:03:02 +0000 Original-Received: (at 31904) by debbugs.gnu.org; 18 Aug 2018 14:02:48 +0000 Original-Received: from localhost ([127.0.0.1]:54182 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fr1oU-0005rM-Iw for submit@debbugs.gnu.org; Sat, 18 Aug 2018 10:02:48 -0400 Original-Received: from mail-wm0-f50.google.com ([74.125.82.50]:39301) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fr1oR-0005qd-0p for 31904@debbugs.gnu.org; Sat, 18 Aug 2018 10:02:44 -0400 Original-Received: by mail-wm0-f50.google.com with SMTP id q8-v6so9803256wmq.4 for <31904@debbugs.gnu.org>; Sat, 18 Aug 2018 07:02:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20161025; h=sender:date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=hK6KcnigA7rWSNVb/jswOM5uTLmggAC5lTaLFeEZijE=; b=LWfD9lOQoSP2Tww60KEfQTY3CSD8RfXi0sfHFC7qYAmxSRMhDIYP2GQz/H3p+MRXy9 46q6qVyN5hk4pfWppbz8QoKLmfiAga/Y2+TJfgZxfB1IS6vHe3ckJXdyC6VMVSARMb6F TXknkq+2Pgj++xWmDMtAoOCDZLXeNQLjPGiihPnWmF9tZlP6itkbbW2bYFnPAL4/VwZW 4EohLi5Oe8Dw9k5xw4YTwBZ6ZAO7HYHZ7Dux0RgaBcvJbEbWCqTHq7LNuG1/RQg2vdcY kL3SKhPvQB7uY3SZoUCaVSWw2A8NT+1gShlAlIJmxUXarkVNvhGfU45qhTl3RbjGexZd pzPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:from:to:cc:subject:message-id :references:mime-version:content-disposition :content-transfer-encoding:in-reply-to:user-agent; bh=hK6KcnigA7rWSNVb/jswOM5uTLmggAC5lTaLFeEZijE=; b=UNeLF1oy/m8eMEI+ef3Y2lQx05vG7sB5BVHS51Iuec3s5XyGk9wnGUzFfBrUDfuHWC CNxWQTCfsb7p8fehU+SQIg/a+fLElpd9G1RImdG+8XbT9Wu1a4TXt3Q5JLHPnxrCDqku Qqr3NgLxxTBqHEsZXA9n6i+xAQJzg3D1svrj+VtSi6ZMgAmIVbYXeuFLMUOpPdajirnK 9uWLLivWJKymwpZanm2ZaVSAcRe9GqhK97PuTTaidf4NijtJ/bv2TnT9qjutSEelqmL0 TJN5DCBsPRtZnwsWVpqitUd1OYiCvCWfA2l6CFpvBOzJbwSR/La9deo+3SaUtHMvR28e BeIw== X-Gm-Message-State: AOUpUlF++8l18ZWy9lTWTBK53210Y1nA5TuRcsonhi90QypRjWxZlvbV j8Ne8bsYc3br3yJeBpwXMvE= X-Google-Smtp-Source: AA+uWPyp1qAyTlIc8fyyca9iizKm+W9/dYke4cgm9ke/jSLwLq3wL2direxgjs0mKw4PHmlUgmpySw== X-Received: by 2002:a1c:93d3:: with SMTP id v202-v6mr21758649wmd.57.1534600957072; Sat, 18 Aug 2018 07:02:37 -0700 (PDT) Original-Received: from breton.holly.idiocy.org (ip6-2001-08b0-03f8-8129-55df-fcd1-50f5-28cb.holly.idiocy.org. [2001:8b0:3f8:8129:55df:fcd1:50f5:28cb]) by smtp.gmail.com with ESMTPSA id m129-v6sm6985300wma.1.2018.08.18.07.02.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 18 Aug 2018 07:02:35 -0700 (PDT) Content-Disposition: inline In-Reply-To: <5C8BCF98-F8C6-465F-99C0-728F25A47982@zentrope.com> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:149569 Archived-At: --Nq2Wo0NMKNjxTN9z Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit On Wed, Aug 15, 2018 at 04:54:26PM -0700, zentrope@fastmail.fm wrote: > For what it’s worth, the scratch/ns-drawing branch has fixed this for me. > > https://github.com/emacs-mirror/emacs/tree/scratch/ns-drawing Thanks for the confirmation. I think I’ll have to port it to Emacs 26. It’s quite a large change, but if Emacs 26 in its current form simply doesn’t work at all with the next release of macOS I don’t see that we have much choice. Can you please try the attached patch against emacs-26? -- Alan Third --Nq2Wo0NMKNjxTN9z Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="0001-Force-all-NS-drawing-to-be-done-from-drawRect.patch" >From 9e71b4aa4ece9ced6b888db403e9ae027501a625 Mon Sep 17 00:00:00 2001 From: Alan Third Date: Sat, 4 Aug 2018 11:08:23 +0100 Subject: [PATCH] Force all NS drawing to be done from drawRect: * 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. (ns_unfocus): Don't unfocus the view any more. (ns_clip_to_row): Update to match ns_focus. (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. --- src/nsterm.m | 736 +++++++++++++++++++++++++-------------------------- 1 file changed, 365 insertions(+), 371 deletions(-) diff --git a/src/nsterm.m b/src/nsterm.m index 5ed71c9f8f..b36d847eb3 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -276,8 +276,6 @@ - (NSColor *)colorUsingDefaultColorSpace long context_menu_value = 0; /* display update */ -static struct frame *ns_updating_frame; -static NSView *focus_view = NULL; static int ns_window_num = 0; #ifdef NS_IMPL_GNUSTEP static NSRect uRect; // TODO: This is dead, remove it? @@ -1055,30 +1053,29 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen) } #endif - ns_updating_frame = f; - [view lockFocus]; - /* drawRect may have been called for say the minibuffer, and then clip path is for the minibuffer. But the display engine may draw more because we have set the frame as garbaged. So reset clip path to the whole view. */ + /* FIXME: I don't think we need to do this. */ #ifdef NS_IMPL_COCOA - { - NSBezierPath *bp; - NSRect r = [view frame]; - NSRect cr = [[view window] frame]; - /* If a large frame size is set, r may be larger than the window frame - before constrained. In that case don't change the clip path, as we - will clear in to the tool bar and title bar. */ - if (r.size.height - + FRAME_NS_TITLEBAR_HEIGHT (f) - + FRAME_TOOLBAR_HEIGHT (f) <= cr.size.height) - { - bp = [[NSBezierPath bezierPathWithRect: r] retain]; - [bp setClip]; - [bp release]; - } - } + if ([NSView focusView] == FRAME_NS_VIEW (f)) + { + NSBezierPath *bp; + NSRect r = [view frame]; + NSRect cr = [[view window] frame]; + /* If a large frame size is set, r may be larger than the window frame + before constrained. In that case don't change the clip path, as we + will clear in to the tool bar and title bar. */ + if (r.size.height + + FRAME_NS_TITLEBAR_HEIGHT (f) + + FRAME_TOOLBAR_HEIGHT (f) <= cr.size.height) + { + bp = [[NSBezierPath bezierPathWithRect: r] retain]; + [bp setClip]; + [bp release]; + } + } #endif #ifdef NS_IMPL_GNUSTEP @@ -1164,23 +1161,14 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen) external (RIF) call; for whole frame, called after update_window_end -------------------------------------------------------------------------- */ { - EmacsView *view = FRAME_NS_VIEW (f); - NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_end"); /* if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */ MOUSE_HL_INFO (f)->mouse_face_defer = 0; - - block_input (); - - [view unlockFocus]; - [[view window] flushWindow]; - - unblock_input (); - ns_updating_frame = NULL; } -static void + +static BOOL ns_focus (struct frame *f, NSRect *r, int n) /* -------------------------------------------------------------------------- Internal: Focus on given frame. During small local updates this is used to @@ -1192,48 +1180,38 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen) -------------------------------------------------------------------------- */ { NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_focus"); - if (r != NULL) + if (r) { NSTRACE_RECT ("r", *r); - } - if (f != ns_updating_frame) - { - NSView *view = FRAME_NS_VIEW (f); - if (view != focus_view) + if ([NSView focusView] == FRAME_NS_VIEW (f)) { - if (focus_view != NULL) - { - [focus_view unlockFocus]; - [[focus_view window] flushWindow]; -/*debug_lock--; */ - } + [[NSGraphicsContext currentContext] saveGraphicsState]; + if (n == 2) + NSRectClipList (r, 2); + else + NSRectClip (*r); + gsaved = YES; - if (view) - [view lockFocus]; - focus_view = view; -/*if (view) debug_lock++; */ + return YES; } - } - - /* clipping */ - if (r) - { - [[NSGraphicsContext currentContext] saveGraphicsState]; - if (n == 2) - NSRectClipList (r, 2); else - NSRectClip (*r); - gsaved = YES; + { + NSView *view = FRAME_NS_VIEW (f); + int i; + for (i = 0 ; i < n ; i++) + [view setNeedsDisplayInRect:r[i]]; + } } + + return NO; } static void ns_unfocus (struct frame *f) -/* -------------------------------------------------------------------------- - Internal: Remove focus on given frame - -------------------------------------------------------------------------- */ +/* Internal: Restore the previous graphics state, unsetting any + clipping areas. */ { NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_unfocus"); @@ -1242,21 +1220,10 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen) [[NSGraphicsContext currentContext] restoreGraphicsState]; gsaved = NO; } - - if (f != ns_updating_frame) - { - if (focus_view != NULL) - { - [focus_view unlockFocus]; - [[focus_view window] flushWindow]; - focus_view = NULL; -/*debug_lock--; */ - } - } } -static void +static BOOL ns_clip_to_row (struct window *w, struct glyph_row *row, enum glyph_row_area area, BOOL gc) /* -------------------------------------------------------------------------- @@ -1275,7 +1242,17 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen) clip_rect.size.width = window_width; clip_rect.size.height = row->visible_height; - ns_focus (f, &clip_rect, 1); + return ns_focus (f, &clip_rect, 1); +} + + +static void +ns_flush_display (struct frame *f) +/* Force the frame to redisplay. If areas have previously been marked + dirty by setNeedsDisplayInRect (in ns_focus), then this will call + draw_rect: which will "expose" those areas. */ +{ + [FRAME_NS_VIEW (f) displayIfNeeded]; } @@ -2699,14 +2676,16 @@ so some key presses (TAB) are swallowed by the system. */ r = [view bounds]; block_input (); - ns_focus (f, &r, 1); - [ns_lookup_indexed_color (NS_FACE_BACKGROUND - (FACE_FROM_ID (f, DEFAULT_FACE_ID)), f) set]; - NSRectFill (r); - ns_unfocus (f); - - /* as of 2006/11 or so this is now needed */ - ns_redraw_scroll_bars (f); + if (ns_focus (f, &r, 1)) + { + [ns_lookup_indexed_color (NS_FACE_BACKGROUND + (FACE_FROM_ID (f, DEFAULT_FACE_ID)), f) set]; + NSRectFill (r); + ns_unfocus (f); + + /* as of 2006/11 or so this is now needed */ + ns_redraw_scroll_bars (f); + } unblock_input (); } @@ -2727,13 +2706,14 @@ so some key presses (TAB) are swallowed by the system. */ NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_clear_frame_area"); r = NSIntersectionRect (r, [view frame]); - ns_focus (f, &r, 1); - [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set]; + if (ns_focus (f, &r, 1)) + { + [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set]; - NSRectFill (r); + NSRectFill (r); - ns_unfocus (f); - return; + ns_unfocus (f); + } } static void @@ -2745,11 +2725,11 @@ so some key presses (TAB) are swallowed by the system. */ { hide_bell(); // Ensure the bell image isn't scrolled. - ns_focus (f, &dest, 1); + /* FIXME: scrollRect:by: is deprecated in macOS 10.14. There is + no obvious replacement so we may have to come up with our own. */ [FRAME_NS_VIEW (f) scrollRect: src by: NSMakeSize (dest.origin.x - src.origin.x, dest.origin.y - src.origin.y)]; - ns_unfocus (f); } } @@ -2960,85 +2940,86 @@ so some key presses (TAB) are swallowed by the system. */ } /* Must clip because of partially visible lines. */ - ns_clip_to_row (w, row, ANY_AREA, YES); - - if (!p->overlay_p) + if (ns_clip_to_row (w, row, ANY_AREA, YES)) { - int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny; - - if (bx >= 0 && nx > 0) + if (!p->overlay_p) { - NSRect r = NSMakeRect (bx, by, nx, ny); - NSRectClip (r); - [ns_lookup_indexed_color (face->background, f) set]; - NSRectFill (r); - } - } - - if (p->which) - { - NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h); - EmacsImage *img = bimgs[p->which - 1]; + int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny; - if (!img) - { - // Note: For "periodic" images, allocate one EmacsImage for - // the base image, and use it for all dh:s. - unsigned short *bits = p->bits; - int full_height = p->h + p->dh; - int i; - unsigned char *cbits = xmalloc (full_height); - - for (i = 0; i < full_height; i++) - cbits[i] = bits[i]; - img = [[EmacsImage alloc] initFromXBM: cbits width: 8 - height: full_height - fg: 0 bg: 0]; - bimgs[p->which - 1] = img; - xfree (cbits); + if (bx >= 0 && nx > 0) + { + NSRect r = NSMakeRect (bx, by, nx, ny); + NSRectClip (r); + [ns_lookup_indexed_color (face->background, f) set]; + NSRectFill (r); + } } - NSTRACE_RECT ("r", r); + if (p->which) + { + NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h); + EmacsImage *img = bimgs[p->which - 1]; - NSRectClip (r); - /* Since we composite the bitmap instead of just blitting it, we need - to erase the whole background. */ - [ns_lookup_indexed_color(face->background, f) set]; - NSRectFill (r); + if (!img) + { + // Note: For "periodic" images, allocate one EmacsImage for + // the base image, and use it for all dh:s. + unsigned short *bits = p->bits; + int full_height = p->h + p->dh; + int i; + unsigned char *cbits = xmalloc (full_height); + + for (i = 0; i < full_height; i++) + cbits[i] = bits[i]; + img = [[EmacsImage alloc] initFromXBM: cbits width: 8 + height: full_height + fg: 0 bg: 0]; + bimgs[p->which - 1] = img; + xfree (cbits); + } - { - NSColor *bm_color; - if (!p->cursor_p) - bm_color = ns_lookup_indexed_color(face->foreground, f); - else if (p->overlay_p) - bm_color = ns_lookup_indexed_color(face->background, f); - else - bm_color = f->output_data.ns->cursor_color; - [img setXBMColor: bm_color]; - } + NSTRACE_RECT ("r", r); -#ifdef NS_IMPL_COCOA - // Note: For periodic images, the full image height is "h + hd". - // By using the height h, a suitable part of the image is used. - NSRect fromRect = NSMakeRect(0, 0, p->wd, p->h); + NSRectClip (r); + /* Since we composite the bitmap instead of just blitting it, we need + to erase the whole background. */ + [ns_lookup_indexed_color(face->background, f) set]; + NSRectFill (r); - NSTRACE_RECT ("fromRect", fromRect); + { + NSColor *bm_color; + if (!p->cursor_p) + bm_color = ns_lookup_indexed_color(face->foreground, f); + else if (p->overlay_p) + bm_color = ns_lookup_indexed_color(face->background, f); + else + bm_color = f->output_data.ns->cursor_color; + [img setXBMColor: bm_color]; + } - [img drawInRect: r - fromRect: fromRect - operation: NSCompositingOperationSourceOver - fraction: 1.0 - respectFlipped: YES - hints: nil]; +#ifdef NS_IMPL_COCOA + // Note: For periodic images, the full image height is "h + hd". + // By using the height h, a suitable part of the image is used. + NSRect fromRect = NSMakeRect(0, 0, p->wd, p->h); + + NSTRACE_RECT ("fromRect", fromRect); + + [img drawInRect: r + fromRect: fromRect + operation: NSCompositingOperationSourceOver + fraction: 1.0 + respectFlipped: YES + hints: nil]; #else - { - NSPoint pt = r.origin; - pt.y += p->h; - [img compositeToPoint: pt operation: NSCompositingOperationSourceOver]; - } + { + NSPoint pt = r.origin; + pt.y += p->h; + [img compositeToPoint: pt operation: NSCompositingOperationSourceOver]; + } #endif + } + ns_unfocus (f); } - ns_unfocus (f); } @@ -3120,67 +3101,66 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. r.size.height = h; r.size.width = w->phys_cursor_width; - /* Prevent the cursor from being drawn outside the text area. */ - ns_clip_to_row (w, glyph_row, TEXT_AREA, NO); /* do ns_focus(f, &r, 1); if remove */ - - - face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id); - if (face && NS_FACE_BACKGROUND (face) - == ns_index_color (FRAME_CURSOR_COLOR (f), f)) + /* Prevent the cursor from being drawn outside the text area. */ + if (ns_clip_to_row (w, glyph_row, TEXT_AREA, NO)) { - [ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), f) set]; - hollow_color = FRAME_CURSOR_COLOR (f); - } - else - [FRAME_CURSOR_COLOR (f) set]; + face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id); + if (face && NS_FACE_BACKGROUND (face) + == ns_index_color (FRAME_CURSOR_COLOR (f), f)) + { + [ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), f) set]; + hollow_color = FRAME_CURSOR_COLOR (f); + } + else + [FRAME_CURSOR_COLOR (f) set]; #ifdef NS_IMPL_COCOA - /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph - atomic. Cleaner ways of doing this should be investigated. - One way would be to set a global variable DRAWING_CURSOR - when making the call to draw_phys..(), don't focus in that - case, then move the ns_unfocus() here after that call. */ - NSDisableScreenUpdates (); + /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph + atomic. Cleaner ways of doing this should be investigated. + One way would be to set a global variable DRAWING_CURSOR + when making the call to draw_phys..(), don't focus in that + case, then move the ns_unfocus() here after that call. */ + NSDisableScreenUpdates (); #endif - switch (cursor_type) - { - case DEFAULT_CURSOR: - case NO_CURSOR: - break; - case FILLED_BOX_CURSOR: - NSRectFill (r); - break; - case HOLLOW_BOX_CURSOR: - NSRectFill (r); - [hollow_color set]; - NSRectFill (NSInsetRect (r, 1, 1)); - [FRAME_CURSOR_COLOR (f) set]; - break; - case HBAR_CURSOR: - NSRectFill (r); - break; - case BAR_CURSOR: - s = r; - /* If the character under cursor is R2L, draw the bar cursor - on the right of its glyph, rather than on the left. */ - cursor_glyph = get_phys_cursor_glyph (w); - if ((cursor_glyph->resolved_level & 1) != 0) - s.origin.x += cursor_glyph->pixel_width - s.size.width; - - NSRectFill (s); - break; - } - ns_unfocus (f); + switch (cursor_type) + { + case DEFAULT_CURSOR: + case NO_CURSOR: + break; + case FILLED_BOX_CURSOR: + NSRectFill (r); + break; + case HOLLOW_BOX_CURSOR: + NSRectFill (r); + [hollow_color set]; + NSRectFill (NSInsetRect (r, 1, 1)); + [FRAME_CURSOR_COLOR (f) set]; + break; + case HBAR_CURSOR: + NSRectFill (r); + break; + case BAR_CURSOR: + s = r; + /* If the character under cursor is R2L, draw the bar cursor + on the right of its glyph, rather than on the left. */ + cursor_glyph = get_phys_cursor_glyph (w); + if ((cursor_glyph->resolved_level & 1) != 0) + s.origin.x += cursor_glyph->pixel_width - s.size.width; + + NSRectFill (s); + break; + } + ns_unfocus (f); - /* draw the character under the cursor */ - if (cursor_type != NO_CURSOR) - draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); + /* draw the character under the cursor */ + if (cursor_type != NO_CURSOR) + draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); #ifdef NS_IMPL_COCOA - NSEnableScreenUpdates (); + NSEnableScreenUpdates (); #endif - + } } @@ -3198,12 +3178,14 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID); - ns_focus (f, &r, 1); - if (face) - [ns_lookup_indexed_color(face->foreground, f) set]; + if (ns_focus (f, &r, 1)) + { + if (face) + [ns_lookup_indexed_color(face->foreground, f) set]; - NSRectFill(r); - ns_unfocus (f); + NSRectFill(r); + ns_unfocus (f); + } } @@ -3230,39 +3212,40 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. NSTRACE ("ns_draw_window_divider"); - ns_focus (f, ÷r, 1); - - if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3)) - /* A vertical divider, at least three pixels wide: Draw first and - last pixels differently. */ - { - [ns_lookup_indexed_color(color_first, f) set]; - NSRectFill(NSMakeRect (x0, y0, 1, y1 - y0)); - [ns_lookup_indexed_color(color, f) set]; - NSRectFill(NSMakeRect (x0 + 1, y0, x1 - x0 - 2, y1 - y0)); - [ns_lookup_indexed_color(color_last, f) set]; - NSRectFill(NSMakeRect (x1 - 1, y0, 1, y1 - y0)); - } - else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3)) - /* A horizontal divider, at least three pixels high: Draw first and - last pixels differently. */ + if (ns_focus (f, ÷r, 1)) { - [ns_lookup_indexed_color(color_first, f) set]; - NSRectFill(NSMakeRect (x0, y0, x1 - x0, 1)); - [ns_lookup_indexed_color(color, f) set]; - NSRectFill(NSMakeRect (x0, y0 + 1, x1 - x0, y1 - y0 - 2)); - [ns_lookup_indexed_color(color_last, f) set]; - NSRectFill(NSMakeRect (x0, y1 - 1, x1 - x0, 1)); - } - else - { - /* In any other case do not draw the first and last pixels - differently. */ - [ns_lookup_indexed_color(color, f) set]; - NSRectFill(divider); - } + if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3)) + /* A vertical divider, at least three pixels wide: Draw first and + last pixels differently. */ + { + [ns_lookup_indexed_color(color_first, f) set]; + NSRectFill(NSMakeRect (x0, y0, 1, y1 - y0)); + [ns_lookup_indexed_color(color, f) set]; + NSRectFill(NSMakeRect (x0 + 1, y0, x1 - x0 - 2, y1 - y0)); + [ns_lookup_indexed_color(color_last, f) set]; + NSRectFill(NSMakeRect (x1 - 1, y0, 1, y1 - y0)); + } + else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3)) + /* A horizontal divider, at least three pixels high: Draw first and + last pixels differently. */ + { + [ns_lookup_indexed_color(color_first, f) set]; + NSRectFill(NSMakeRect (x0, y0, x1 - x0, 1)); + [ns_lookup_indexed_color(color, f) set]; + NSRectFill(NSMakeRect (x0, y0 + 1, x1 - x0, y1 - y0 - 2)); + [ns_lookup_indexed_color(color_last, f) set]; + NSRectFill(NSMakeRect (x0, y1 - 1, x1 - x0, 1)); + } + else + { + /* In any other case do not draw the first and last pixels + differently. */ + [ns_lookup_indexed_color(color, f) set]; + NSRectFill(divider); + } - ns_unfocus (f); + ns_unfocus (f); + } } static void @@ -3846,83 +3829,84 @@ Function modeled after x_draw_glyph_string_box (). n = ns_get_glyph_string_clip_rect (s, r); *r = NSMakeRect (s->x, s->y, s->background_width, s->height); - ns_focus (s->f, r, n); - - if (s->hl == DRAW_MOUSE_FACE) - { - face = FACE_FROM_ID_OR_NULL (s->f, - MOUSE_HL_INFO (s->f)->mouse_face_face_id); - if (!face) - face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); - } - else - face = FACE_FROM_ID (s->f, s->first_glyph->face_id); - - bgCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f); - fgCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f); - - for (i = 0; i < n; ++i) + if (ns_focus (s->f, r, n)) { - if (!s->row->full_width_p) + if (s->hl == DRAW_MOUSE_FACE) { - int overrun, leftoverrun; - - /* truncate to avoid overwriting fringe and/or scrollbar */ - overrun = max (0, (s->x + s->background_width) - - (WINDOW_BOX_RIGHT_EDGE_X (s->w) - - WINDOW_RIGHT_FRINGE_WIDTH (s->w))); - r[i].size.width -= overrun; - - /* truncate to avoid overwriting to left of the window box */ - leftoverrun = (WINDOW_BOX_LEFT_EDGE_X (s->w) - + WINDOW_LEFT_FRINGE_WIDTH (s->w)) - s->x; - - if (leftoverrun > 0) - { - r[i].origin.x += leftoverrun; - r[i].size.width -= leftoverrun; - } - - /* XXX: Try to work between problem where a stretch glyph on - a partially-visible bottom row will clear part of the - modeline, and another where list-buffers headers and similar - rows erroneously have visible_height set to 0. Not sure - where this is coming from as other terms seem not to show. */ - r[i].size.height = min (s->height, s->row->visible_height); + face = FACE_FROM_ID_OR_NULL (s->f, + MOUSE_HL_INFO (s->f)->mouse_face_face_id); + if (!face) + face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); } + else + face = FACE_FROM_ID (s->f, s->first_glyph->face_id); - [bgCol set]; + bgCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f); + fgCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f); - /* NOTE: under NS this is NOT used to draw cursors, but we must avoid - overwriting cursor (usually when cursor on a tab) */ - if (s->hl == DRAW_CURSOR) + for (i = 0; i < n; ++i) { - CGFloat x, width; + if (!s->row->full_width_p) + { + int overrun, leftoverrun; + + /* truncate to avoid overwriting fringe and/or scrollbar */ + overrun = max (0, (s->x + s->background_width) + - (WINDOW_BOX_RIGHT_EDGE_X (s->w) + - WINDOW_RIGHT_FRINGE_WIDTH (s->w))); + r[i].size.width -= overrun; + + /* truncate to avoid overwriting to left of the window box */ + leftoverrun = (WINDOW_BOX_LEFT_EDGE_X (s->w) + + WINDOW_LEFT_FRINGE_WIDTH (s->w)) - s->x; + + if (leftoverrun > 0) + { + r[i].origin.x += leftoverrun; + r[i].size.width -= leftoverrun; + } + + /* XXX: Try to work between problem where a stretch glyph on + a partially-visible bottom row will clear part of the + modeline, and another where list-buffers headers and similar + rows erroneously have visible_height set to 0. Not sure + where this is coming from as other terms seem not to show. */ + r[i].size.height = min (s->height, s->row->visible_height); + } + + [bgCol set]; - x = r[i].origin.x; - width = s->w->phys_cursor_width; - r[i].size.width -= width; - r[i].origin.x += width; + /* NOTE: under NS this is NOT used to draw cursors, but we must avoid + overwriting cursor (usually when cursor on a tab). */ + if (s->hl == DRAW_CURSOR) + { + CGFloat x, width; + + x = r[i].origin.x; + width = s->w->phys_cursor_width; + r[i].size.width -= width; + r[i].origin.x += width; - NSRectFill (r[i]); + NSRectFill (r[i]); - /* Draw overlining, etc. on the cursor. */ - if (s->w->phys_cursor_type == FILLED_BOX_CURSOR) - ns_draw_text_decoration (s, face, bgCol, width, x); + /* Draw overlining, etc. on the cursor. */ + if (s->w->phys_cursor_type == FILLED_BOX_CURSOR) + ns_draw_text_decoration (s, face, bgCol, width, x); + else + ns_draw_text_decoration (s, face, fgCol, width, x); + } else - ns_draw_text_decoration (s, face, fgCol, width, x); - } - else - { - NSRectFill (r[i]); - } + { + NSRectFill (r[i]); + } - /* Draw overlining, etc. on the stretch glyph (or the part - of the stretch glyph after the cursor). */ - ns_draw_text_decoration (s, face, fgCol, r[i].size.width, - r[i].origin.x); + /* Draw overlining, etc. on the stretch glyph (or the part + of the stretch glyph after the cursor). */ + ns_draw_text_decoration (s, face, fgCol, r[i].size.width, + r[i].origin.x); + } + ns_unfocus (s->f); } - ns_unfocus (s->f); s->background_filled_p = 1; } } @@ -4072,9 +4056,11 @@ overwriting cursor (usually when cursor on a tab) */ if (next->first_glyph->type != STRETCH_GLYPH) { n = ns_get_glyph_string_clip_rect (s->next, r); - ns_focus (s->f, r, n); - ns_maybe_dumpglyphs_background (s->next, 1); - ns_unfocus (s->f); + if (ns_focus (s->f, r, n)) + { + ns_maybe_dumpglyphs_background (s->next, 1); + ns_unfocus (s->f); + } } else { @@ -4089,10 +4075,12 @@ overwriting cursor (usually when cursor on a tab) */ || s->first_glyph->type == COMPOSITE_GLYPH)) { n = ns_get_glyph_string_clip_rect (s, r); - ns_focus (s->f, r, n); - ns_maybe_dumpglyphs_background (s, 1); - ns_dumpglyphs_box_or_relief (s); - ns_unfocus (s->f); + if (ns_focus (s->f, r, n)) + { + ns_maybe_dumpglyphs_background (s, 1); + ns_dumpglyphs_box_or_relief (s); + ns_unfocus (s->f); + } box_drawn_p = 1; } @@ -4101,9 +4089,11 @@ overwriting cursor (usually when cursor on a tab) */ case IMAGE_GLYPH: n = ns_get_glyph_string_clip_rect (s, r); - ns_focus (s->f, r, n); - ns_dumpglyphs_image (s, r[0]); - ns_unfocus (s->f); + if (ns_focus (s->f, r, n)) + { + ns_dumpglyphs_image (s, r[0]); + ns_unfocus (s->f); + } break; case STRETCH_GLYPH: @@ -4113,66 +4103,68 @@ overwriting cursor (usually when cursor on a tab) */ case CHAR_GLYPH: case COMPOSITE_GLYPH: n = ns_get_glyph_string_clip_rect (s, r); - ns_focus (s->f, r, n); + if (ns_focus (s->f, r, n)) + { + if (s->for_overlaps || (s->cmp_from > 0 + && ! s->first_glyph->u.cmp.automatic)) + s->background_filled_p = 1; + else + ns_maybe_dumpglyphs_background + (s, s->first_glyph->type == COMPOSITE_GLYPH); - if (s->for_overlaps || (s->cmp_from > 0 - && ! s->first_glyph->u.cmp.automatic)) - s->background_filled_p = 1; - else - ns_maybe_dumpglyphs_background - (s, s->first_glyph->type == COMPOSITE_GLYPH); + if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR) + { + unsigned long tmp = NS_FACE_BACKGROUND (s->face); + NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face); + NS_FACE_FOREGROUND (s->face) = tmp; + } - if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR) - { - unsigned long tmp = NS_FACE_BACKGROUND (s->face); - NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face); - NS_FACE_FOREGROUND (s->face) = tmp; - } + { + BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH; - { - BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH; + if (isComposite) + ns_draw_composite_glyph_string_foreground (s); + else + ns_draw_glyph_string_foreground (s); + } - if (isComposite) - ns_draw_composite_glyph_string_foreground (s); - else - ns_draw_glyph_string_foreground (s); - } + { + NSColor *col = (NS_FACE_FOREGROUND (s->face) != 0 + ? ns_lookup_indexed_color (NS_FACE_FOREGROUND (s->face), + s->f) + : FRAME_FOREGROUND_COLOR (s->f)); + [col set]; + + /* Draw underline, overline, strike-through. */ + ns_draw_text_decoration (s, s->face, col, s->width, s->x); + } - { - NSColor *col = (NS_FACE_FOREGROUND (s->face) != 0 - ? ns_lookup_indexed_color (NS_FACE_FOREGROUND (s->face), - s->f) - : FRAME_FOREGROUND_COLOR (s->f)); - [col set]; - - /* Draw underline, overline, strike-through. */ - ns_draw_text_decoration (s, s->face, col, s->width, s->x); - } + if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR) + { + unsigned long tmp = NS_FACE_BACKGROUND (s->face); + NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face); + NS_FACE_FOREGROUND (s->face) = tmp; + } - if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR) - { - unsigned long tmp = NS_FACE_BACKGROUND (s->face); - NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face); - NS_FACE_FOREGROUND (s->face) = tmp; + ns_unfocus (s->f); } - - ns_unfocus (s->f); break; case GLYPHLESS_GLYPH: n = ns_get_glyph_string_clip_rect (s, r); - ns_focus (s->f, r, n); - - if (s->for_overlaps || (s->cmp_from > 0 - && ! s->first_glyph->u.cmp.automatic)) - s->background_filled_p = 1; - else - ns_maybe_dumpglyphs_background - (s, s->first_glyph->type == COMPOSITE_GLYPH); - /* ... */ - /* Not yet implemented. */ - /* ... */ - ns_unfocus (s->f); + if (ns_focus (s->f, r, n)) + { + if (s->for_overlaps || (s->cmp_from > 0 + && ! s->first_glyph->u.cmp.automatic)) + s->background_filled_p = 1; + else + ns_maybe_dumpglyphs_background + (s, s->first_glyph->type == COMPOSITE_GLYPH); + /* ... */ + /* Not yet implemented. */ + /* ... */ + ns_unfocus (s->f); + } break; default: @@ -4183,9 +4175,11 @@ overwriting cursor (usually when cursor on a tab) */ if (!s->for_overlaps && !box_drawn_p && s->face->box != FACE_NO_BOX) { n = ns_get_glyph_string_clip_rect (s, r); - ns_focus (s->f, r, n); - ns_dumpglyphs_box_or_relief (s); - ns_unfocus (s->f); + if (ns_focus (s->f, r, n)) + { + ns_dumpglyphs_box_or_relief (s); + ns_unfocus (s->f); + } } s->num_clips = 0; @@ -4991,7 +4985,7 @@ static Lisp_Object ns_string_to_lispmod (const char *s) ns_after_update_window_line, ns_update_window_begin, ns_update_window_end, - 0, /* flush_display */ + ns_flush_display, /* flush_display */ x_clear_window_mouse_face, x_get_glyph_overhangs, x_fix_overlapping_area, -- 2.17.1 --Nq2Wo0NMKNjxTN9z--