When the animation layer is enabled, draw the cursor only in the
compositor (skip the static one in mtl_draw_window_cursor) so there is
no double cursor, and feed the animator the real FRAME_CURSOR_COLOR
instead of the hardcoded cyan used for the trail and cursor quads.
mtl_draw_glyph_string ignored face->box, so boxed faces (mode line with its
released-button relief, buttons, etc.) rendered flat. Port
ns_dumpglyphs_box_or_relief: compute the box rect and left/right edge presence
from the glyph string, then draw the four edges. FACE_SIMPLE_BOX uses box_color;
raised/sunken reliefs use highlight/shadow shades of the base (box_color or
background) at level 0.4, matching NSColor highlightWithLevel:/shadowWithLevel:.
Mode line now shows its 3D border; the bottom/right shadow matches NS. The
top/left highlight is a touch brighter than NS (subtle 1px), to refine later.
mtl_draw_vertical_window_border and mtl_draw_window_divider hardcoded 0x4C566A.
Port the NS logic: vertical border uses VERTICAL_BORDER_FACE_ID; window divider
uses WINDOW_DIVIDER_FACE_ID with distinct first/last pixel faces
(WINDOW_DIVIDER_FIRST/LAST_PIXEL_FACE_ID) for wide/tall dividers, falling back
to the frame foreground.
mtl_draw_fringe_bitmap was a stub, so truncation/continuation arrows, the
buffer-boundary and other fringe indicators never appeared. Implement it
mirroring ns_draw_fringe_bitmap: clear the fringe background (and the wider bx
area) unless overlay, then rasterize p->bits (MSB-first rows, visible window
[dh, dh+h)) into a one-shot R8 coverage texture and draw it as a colored quad
through the glyph pipeline. Color is face->foreground, or the cursor color when
cursor_p. A fresh texture per call avoids the deferred-sampling hazard of
sharing one texture across queued draws.
Verified: the truncation arrow now matches the NS backend.
mtl_scroll_run was a stub that only nudged the animator, so Emacs's scroll
optimization left stale/duplicated text: scrolling (C-v, recenter) and any
re-layout (window split, *Completions*/*Warnings* popups) painted new rows over
the old ones because the moved block was never relocated.
Now mtl_scroll_run mirrors ns_scroll_run's geometry (window_box +
WINDOW_TO_FRAME_PIXEL_Y, clamped to avoid the mode line) and moves the block
inside the static texture with a GPU blit. Since a single copy can't overlap
its own source/destination, it bounces the region through a scratch texture.
The render encoder is ended and reopened (LOAD) around the blit so subsequent
draw_glyph_string calls land on the moved pixels; Metal's hazard tracking
orders the copy after the draws. Encoder creation is factored into
openRenderEncoderClear:.
Verified with the comparison harness: scrolling and split/relayout no longer
leave ghost text.
- mtl_draw_glyph_string advanced the pen by CoreText's fractional glyph advance
instead of Emacs's layout grid. Across a line the drift accumulated, glyphs
landed at fractional positions (linear-sampling blur) and progressively
overlapped/clipped. Advance by first_glyph[i].pixel_width at integer
positions so Metal stays locked to Emacs's grid and the 1:1 blit is crisp.
- Disable CoreText font smoothing in the glyph rasterization context: the
white-on-black mask was stem-darkened, making text heavier than NS
(mean gray 220 vs 226). Now ~228, matching NS within ~1.7 levels.
- Add g_mtl_animations_enabled (default off): the 60fps compositor overlay
(cyan cursor, particles, CADisplayLink) is now opt-in via (mtl-animations t)
/ mtl-toggle-animations. With it off, compositeToScreen only blits + presents,
removing the stray cyan cursor box that tinted the frame.
- Draw the cursor directly into the static texture like the NS backend
(get_phys_cursor_glyph + get_phys_cursor_geometry, FRAME_CURSOR_COLOR,
filled/hollow/bar/hbar), and handle DRAW_CURSOR in mtl_draw_glyph_string so
the glyph under a filled cursor stays readable (inverse).
- Fix glyph vertical baseline: bearing_y stored the descent instead of the
distance from the cell top to the baseline, dropping every glyph ~one ascent
too low and overlapping the next line / mode line. Store bh-1-raster_oy.
Three critical bugs fixed:
1. MTLLoadActionClear wipes staticTexture every update_begin cycle.
Emacs calls update_begin/end multiple times per second (cursor blink,
modeline, etc.). Each call was clearing all previously drawn content.
Fix: only clear on texture (re)creation; use MTLLoadActionLoad to
PRESERVE content between update_begin cycles. Emacs's draw_glyph_string
fills backgrounds only for the regions being updated.
2. char2b contains CGGlyph IDs (not Unicode codepoints) in the macfont
backend. mtl_draw_glyph_string was calling mtl_cache_glyph() which
used CTFontGetGlyphsForCharacters (Unicode→glyph) on values that were
already glyph IDs — double conversion, wrong glyphs rendered.
Fix: new mtl_cache_glyph_id() uses CTFontDrawGlyphs directly with the
glyph ID from char2b, same as ns_draw_glyph_string_foreground does.
3. mtl_patch_terminal_rif replaced the ENTIRE terminal rif (including
NULL frame_parm_handlers). init_frame_faces/realize_basic_faces accesses
rif->frame_parm_handlers during Fx_create_frame → SIGSEGV.
Fix: copy the NS rif (preserving frame_parm_handlers and all management
functions), then override ONLY the pixel-drawing functions with Metal.
Added: mtl-capture-frame, mtl-draw-stats diagnostics (kept for debugging).
Root cause (macOS 26.5):
NSMapTable with NSMapTableObjectPointerPersonality used the NSValue*
wrapper POINTER ADDRESS for equality, not the wrapped struct image*
content. This caused:
1. Cache always missed (two NSValue objects wrapping same pointer
are NOT equal by address)
2. NSValue objects leaked in the map table indefinitely
3. On macOS 26.5, NSMapTable's internal GCD-backed implementation
confused leaked NSValue memory regions with OS_dispatch_source
objects, causing -[OS_dispatch_source objectForKey:] crash in
mtl_draw_glyph_string on first IMAGE_GLYPH render
Fix: CFMutableDictionaryRef with NULL key callbacks uses raw pointer
equality (struct image* directly as key) with CF retain for values.
No NSValue wrapper, no ObjC runtime quirks.
Also fixed: NSWindowDidChangeScreenNotification observer was created
with addObserverForName:object:queue:usingBlock: but the returned
observer TOKEN was dropped. On macOS 26.5 the token is internally an
OS_dispatch_source; when the autoreleased token was freed, the memory
could be reused by adjacent static variables. Fixed by replacing the
notification with a KVO observer on the 'window' key path using the
existing MtlResizeObserver (stored as associated object, safe lifetime).
CGBitmapInfo fix: use kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little
instead of Big-endian RGBA. Metal BGRA8Unorm expects little-endian byte order,
avoiding a separate R<->B swap pass.
When a plstore has entries with secret keys, processing the plstore
file would require decryption first. However, unlike other functions
like 'plstore-get', 'plstore-put', etc., 'plstore-delete' does not
check for secret keys and decrypt the file, which would corrupt the
file when deleting any entries with secret keys.
This patch adds checking for secret keys and decrypt the file when
needed before removing the entry with name.
* lisp/plstore.el (plstore--has-secret-keys): New.
* lisp/plstore.el (plstore-delete): Check for secret keys of the entry
and decrypt plstore before performing the deletion. (Bug#81061)
* src/xterm.c (x_suspend_background_fills)
(x_restore_background_fills): New functions.
(x_set_window_size, x_set_window_size_and_position)
(x_make_frame_invisible): Use them (bug#80961).
Ported from emacs-31 release branch:
commit 984932d4dc
Author: Sean Whitton <spwhitton@spwhitton.name>
Date: Mon Jun 1 11:48:42 2026 +0100
Disable markdown-ts-mode & markdown-ts-view-mode for Emacs 31
This synchronizes master's Eglot with emacs-31. The goal of that commit
is to demote those markdown-ts-mode.el modes to "experimental" status in
emacs-31, but Eglot was already relying on them and changes were needed.
984932d4dc is not the commit that best
does those changes, but since that commit was marked "do not merge" on
emacs-31, I thought it best to bring it here manually so any further
work -- which doesn't contradict the overarching intention -- can
continue in emacs-31 with clean merges to master (where the GNU-devel
core Elpa package is pulled from).
* lisp/progmodes/eglot.el (eglot-documentation-renderer)
(eglot--format-markup): Don't call eglot--builtin-mdown-p.
* doc/misc/eglot.texi (Customization Variables):
* etc/EGLOT-NEWS: Don't mention markdown-ts-mode
Co-authored-by: Sean Whitton <spwhitton@spwhitton.name>
Problem reported by Helmut Eller (Bug#81132#25).
* src/dispextern.h (IF_DEBUG): Omit cast that is useless if
the argument is already void.
* src/ftfont.c (adjust_anchor): Omit useless cast.
* Makefile.in (MAKE_DOC_FOR_DOCLANG): Remove unnecessary .PHONY
definitions for targets which will be encompassed by $(DOC).
(MAKE_DOC): Create a common target to to which to assign runtime
dependencies.
(misc-info-common, misc-dvi-common, misc-html-common)
(misc-pdf-common, misc-ps-common): Assign runtime dependencies
on Lisp etc. previously assigned to the bare targets now subject
to indirection.
* lib-src/emacsclient.c: Include <stdckdint.h>
(timeout): Now signed, and initially -1. All uses changed.
(decode_options): Do not worry about ERANGE or ranges, as other
code now deal with this; the old code was wrong anyway as it mixed
uintmax_t with INTMAX_MAX and INTMAX_MIN. But do check for syntax
errors and negative values.
(set_socket_timeout): Don’t time out if the timeout is 0 or enormous.
Silently ignore errors (Bug#81160).
(main): Allow --timeout=0, as per documentation.
This also avoids using ";" in make rules, which doesn't propagate
errors from the first command to the entire line.
* Makefile.in (MAKE_DOC_FOR_DOCLANG): New.
(MAKE_DOC): delegate to 'MAKE_DOC_FOR_DOCLANG' per language doc build.
Amend commit 75153f7b76 " Fix clash with locale variable" by Andreas Schwab.
Use DOCLANG instead of INFO_LANG for renaming, as documentation does not
produce only info output, and DOCLANG is iterating over DOCLANGS.
* Makefile.in: Rename 'LANG' to 'DOCLANG' to avoid clash with well-known
environment variable.
* doc/misc/Makefile.in: Adjusted accordingly, rename 'INFO_LANG' to 'DOCLANG'
where Andreas had already renamed 'LANG'.
* doc/translations/fr/misc/ses-fr.texi: rename 'INFO_LANG' to 'DOCLANG' in
explanatory comment.
LANG is a locale variable, use INFO_LANG instead.
* doc/misc/Makefile.in (INFO_LANG): Renamed from LANG, all uses
changed.
* doc/translations/fr/misc/ses-fr.texi: Use INFO_LANG instead of
LANG.
* src/term.c (syms_of_term) <tty-cursor-movement-use-TAB>: New var.
<tty-cursor-movement-use-TAB-BS>: Doc fix.
* src/cm.c (calccost): Use it to disable use of TABs for cursor
motion on text terminals.
* etc/NEWS: Announce the new variable.
* doc/misc/Makefile.in (INFO_TARGETS): Always build efaq-w32.info.
(info_template): Remove unnecessary extra prerequisite for
$$(buildinfodir)/$(1)$$(lang_suffix).info, which repeats an
existing pattern rule and causes ccmode.info be constantly
regenerated.
The old boolean 'eglot-prefer-plaintext' is replaced by the more
expressive 'eglot-documentation-renderer', which can hold a major-mode
symbol, t (plain text), or nil (auto-detect each time). By selecting a
renderer once at startup the repeated per-request lookups are avoided,
which helps with the slowness reported in bug#81150.
* lisp/progmodes/eglot.el (eglot-prefer-plaintext): Declare obsolete
alias to 'eglot-documentation-renderer'.
(eglot-documentation-renderer): New defcustom, reworked from from
eglot-prefer-plaintext.
(eglot--accepted-formats): Use new variable.
(eglot--format-markup): Use new variable.
* etc/EGLOT-NEWS: Announce change.
* doc/misc/eglot.texi (Customization Variables): Document
eglot-documentation-renderer.
* lisp/net/eww.el (eww-form-submit): Call put-text-property to
add help-echo and shr-tab-stop properties.
(eww-tag-input): Exclude inputs with type="submit" when adding
the help-echo and shr-tab-stop properties, since that's now done
in eww-form-submit, called earlier for type="submit".
72d890c43e ; Update the documentation of 'debug'
69fd4b87f4 Don't make buffer read-only when reverting if 'view-mode'...
2955b51e80 ; * etc/NEWS: Document the change in mode-line faces.
# Conflicts:
# etc/NEWS