aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHelmut Eller2026-04-04 20:59:46 +0200
committerHelmut Eller2026-04-04 20:59:46 +0200
commit6eec001187e8551f32b6498e6dc60cdc58c2e515 (patch)
tree13233de9f0a05ef86a51500e8b1870b75ff20c81 /src
parente4ea27119e79012f9d651cb61d1115589d91ef39 (diff)
parent01a9d78a7e4c7d7fa5b799e4fdc2caf77a012734 (diff)
downloademacs-feature/igc3.tar.gz
emacs-feature/igc3.zip
Merge branch 'master' into feature/igc3feature/igc3
Diffstat (limited to 'src')
-rw-r--r--src/bidi.c10
-rw-r--r--src/charset.c10
-rw-r--r--src/chartab.c2
-rw-r--r--src/dispnew.c7
-rw-r--r--src/dosfns.c3
-rw-r--r--src/fileio.c3
-rw-r--r--src/frame.c17
-rw-r--r--src/keyboard.c4
-rw-r--r--src/lisp.h2
-rw-r--r--src/menu.c3
-rw-r--r--src/msdos.c2
-rw-r--r--src/nsterm.m197
-rw-r--r--src/pgtkterm.c28
-rw-r--r--src/sysdep.c3
-rw-r--r--src/term.c10
-rw-r--r--src/terminal.c27
-rw-r--r--src/w32xfns.c2
-rw-r--r--src/xdisp.c33
-rw-r--r--src/xfaces.c10
19 files changed, 292 insertions, 81 deletions
diff --git a/src/bidi.c b/src/bidi.c
index f4bca186177..9cf53787c4b 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -367,6 +367,8 @@ bidi_isolate_fmt_char (bidi_type_t ch_type)
367 return (ch_type == LRI || ch_type == RLI || ch_type == PDI || ch_type == FSI); 367 return (ch_type == LRI || ch_type == RLI || ch_type == PDI || ch_type == FSI);
368} 368}
369 369
370static void bidi_initialize (void);
371
370/* Return the mirrored character of C, if it has one. If C has no 372/* Return the mirrored character of C, if it has one. If C has no
371 mirrored counterpart, return C. 373 mirrored counterpart, return C.
372 Note: The conditions in UAX#9 clause L4 regarding the surrounding 374 Note: The conditions in UAX#9 clause L4 regarding the surrounding
@@ -381,6 +383,14 @@ bidi_mirror_char (int c)
381 if (c < 0 || c > MAX_CHAR) 383 if (c < 0 || c > MAX_CHAR)
382 emacs_abort (); 384 emacs_abort ();
383 385
386 /* We can be called at the very beginning of init_iterator, via
387 produce_special_glyphs, and the first such call in a session might
388 happen when the bidi-mirroring table was not yet initialized. Make
389 sure we do this now. */
390 if (!CHAR_TABLE_P (bidi_mirror_table)
391 && !bidi_initialized)
392 bidi_initialize ();
393
384 val = CHAR_TABLE_REF (bidi_mirror_table, c); 394 val = CHAR_TABLE_REF (bidi_mirror_table, c);
385 if (FIXNUMP (val)) 395 if (FIXNUMP (val))
386 { 396 {
diff --git a/src/charset.c b/src/charset.c
index 041f350cf8e..524966d5fbc 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -799,7 +799,7 @@ Optional 4th and 5th arguments FROM-CODE and TO-CODE specify the
799range of code points (in CHARSET) of target characters on which to 799range of code points (in CHARSET) of target characters on which to
800map the FUNCTION. Note that these are not character codes, but code 800map the FUNCTION. Note that these are not character codes, but code
801points of CHARSET; for the difference see `decode-char' and 801points of CHARSET; for the difference see `decode-char' and
802`list-charset-chars'. If FROM-CODE is nil or imitted, it stands for 802`list-charset-chars'. If FROM-CODE is nil or omitted, it stands for
803the first code point of CHARSET; if TO-CODE is nil or omitted, it 803the first code point of CHARSET; if TO-CODE is nil or omitted, it
804stands for the last code point of CHARSET. 804stands for the last code point of CHARSET.
805 805
@@ -840,7 +840,7 @@ TO-CODE, which are CHARSET code points. */)
840/* Define a charset according to the arguments. The Nth argument is 840/* Define a charset according to the arguments. The Nth argument is
841 the Nth attribute of the charset (the last attribute `charset-id' 841 the Nth attribute of the charset (the last attribute `charset-id'
842 is not included). See the docstring of `define-charset' for the 842 is not included). See the docstring of `define-charset' for the
843 detail. */ 843 details. */
844 844
845DEFUN ("define-charset-internal", Fdefine_charset_internal, 845DEFUN ("define-charset-internal", Fdefine_charset_internal,
846 Sdefine_charset_internal, charset_arg_max, MANY, 0, 846 Sdefine_charset_internal, charset_arg_max, MANY, 0,
@@ -1530,7 +1530,7 @@ BEG and END are buffer positions.
1530Optional arg TABLE if non-nil is a translation table to look up. 1530Optional arg TABLE if non-nil is a translation table to look up.
1531 1531
1532If the current buffer is unibyte, the returned list may contain 1532If the current buffer is unibyte, the returned list may contain
1533only `ascii', `eight-bit-control', and `eight-bit-graphic'. */) 1533only `ascii' and `eight-bit'. */)
1534 (Lisp_Object beg, Lisp_Object end, Lisp_Object table) 1534 (Lisp_Object beg, Lisp_Object end, Lisp_Object table)
1535{ 1535{
1536 Lisp_Object charsets; 1536 Lisp_Object charsets;
@@ -1581,7 +1581,7 @@ DEFUN ("find-charset-string", Ffind_charset_string, Sfind_charset_string,
1581Optional arg TABLE if non-nil is a translation table to look up. 1581Optional arg TABLE if non-nil is a translation table to look up.
1582 1582
1583If STR is unibyte, the returned list may contain 1583If STR is unibyte, the returned list may contain
1584only `ascii', `eight-bit-control', and `eight-bit-graphic'. */) 1584only `ascii' and `eight-bit'. */)
1585 (Lisp_Object str, Lisp_Object table) 1585 (Lisp_Object str, Lisp_Object table)
1586{ 1586{
1587 CHECK_STRING (str); 1587 CHECK_STRING (str);
@@ -2036,7 +2036,7 @@ ASCII characters are an exception: for them, this function always
2036returns `ascii'. 2036returns `ascii'.
2037If optional 2nd arg RESTRICTION is non-nil, it is a list of charsets 2037If optional 2nd arg RESTRICTION is non-nil, it is a list of charsets
2038from which to find the charset. It may also be a coding system. In 2038from which to find the charset. It may also be a coding system. In
2039that case, find the charset from what supported by that coding system. */) 2039that case, find the charset in those supported by that coding system. */)
2040 (Lisp_Object ch, Lisp_Object restriction) 2040 (Lisp_Object ch, Lisp_Object restriction)
2041{ 2041{
2042 struct charset *charset; 2042 struct charset *charset;
diff --git a/src/chartab.c b/src/chartab.c
index 3076f72c06e..7d2710f20a3 100644
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -78,7 +78,7 @@ sub_char_table_ref_and_range (Lisp_Object, int, int *, int *,
78/* Nonzero iff OBJ is a string representing uniprop values of 128 78/* Nonzero iff OBJ is a string representing uniprop values of 128
79 succeeding characters (the bottom level of a char-table) by a 79 succeeding characters (the bottom level of a char-table) by a
80 compressed format. We are sure that no property value has a string 80 compressed format. We are sure that no property value has a string
81 starting with '\001' nor '\002'. */ 81 starting with '\001' or '\002'. */
82#define UNIPROP_COMPRESSED_FORM_P(OBJ) \ 82#define UNIPROP_COMPRESSED_FORM_P(OBJ) \
83 (STRINGP (OBJ) && SCHARS (OBJ) > 0 \ 83 (STRINGP (OBJ) && SCHARS (OBJ) > 0 \
84 && ((SREF (OBJ, 0) == 1 || (SREF (OBJ, 0) == 2)))) 84 && ((SREF (OBJ, 0) == 1 || (SREF (OBJ, 0) == 2))))
diff --git a/src/dispnew.c b/src/dispnew.c
index 15d3c2a599a..45211b9d2e9 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -6826,8 +6826,7 @@ FILE = nil means just close any termscript file currently open. */)
6826{ 6826{
6827 struct tty_display_info *tty; 6827 struct tty_display_info *tty;
6828 6828
6829 if (! FRAME_TERMCAP_P (SELECTED_FRAME ()) 6829 if (!is_tty_frame (SELECTED_FRAME ()))
6830 && ! FRAME_MSDOS_P (SELECTED_FRAME ()))
6831 error ("Current frame is not on a tty device"); 6830 error ("Current frame is not on a tty device");
6832 6831
6833 tty = CURTTY (); 6832 tty = CURTTY ();
@@ -7394,7 +7393,7 @@ init_display_interactive (void)
7394 t = init_tty (0, terminal_type, 1); /* Errors are fatal. */ 7393 t = init_tty (0, terminal_type, 1); /* Errors are fatal. */
7395 7394
7396 /* Convert the initial frame to use the new display. */ 7395 /* Convert the initial frame to use the new display. */
7397 if (f->output_method != output_initial) 7396 if (!FRAME_INITIAL_P (f))
7398 emacs_abort (); 7397 emacs_abort ();
7399 f->output_method = t->type; 7398 f->output_method = t->type;
7400 f->terminal = t; 7399 f->terminal = t;
@@ -7404,7 +7403,7 @@ init_display_interactive (void)
7404 f->output_data.tty = &the_only_tty_output; 7403 f->output_data.tty = &the_only_tty_output;
7405 f->output_data.tty->display_info = &the_only_display_info; 7404 f->output_data.tty->display_info = &the_only_display_info;
7406#else 7405#else
7407 if (f->output_method == output_termcap) 7406 if (FRAME_TERMCAP_P (f))
7408 create_tty_output (f); 7407 create_tty_output (f);
7409#endif 7408#endif
7410 t->display_info.tty->top_frame = selected_frame; 7409 t->display_info.tty->top_frame = selected_frame;
diff --git a/src/dosfns.c b/src/dosfns.c
index 414cc550510..07d553b0d78 100644
--- a/src/dosfns.c
+++ b/src/dosfns.c
@@ -681,8 +681,7 @@ dos_cleanup (void)
681 { 681 {
682 struct frame *sf = XFRAME (selected_frame); 682 struct frame *sf = XFRAME (selected_frame);
683 683
684 if (FRAME_LIVE_P (sf) 684 if (FRAME_LIVE_P (sf) && is_tty_frame (sf))
685 && (FRAME_MSDOS_P (sf) || FRAME_TERMCAP_P (sf)))
686 { 685 {
687 tty = CURTTY (); 686 tty = CURTTY ();
688 if (tty->termscript) 687 if (tty->termscript)
diff --git a/src/fileio.c b/src/fileio.c
index 2d62bb21c17..cf77bfec695 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -774,6 +774,9 @@ Do not expand PREFIX; a non-absolute PREFIX is relative to the Emacs
774working directory. If TEXT is a string, insert it into the newly 774working directory. If TEXT is a string, insert it into the newly
775created file. 775created file.
776 776
777On Posix systems, the file/directory is created with access mode bits
778that limit access to the current user.
779
777Signal an error if the file could not be created. 780Signal an error if the file could not be created.
778 781
779This function does not grok magic file names. */) 782This function does not grok magic file names. */)
diff --git a/src/frame.c b/src/frame.c
index 20481c230d1..2475eb84df3 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -214,7 +214,7 @@ frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
214 && !NILP (fullscreen) && !EQ (fullscreen, Qfullheight)) 214 && !NILP (fullscreen) && !EQ (fullscreen, Qfullheight))
215 || (!horizontal 215 || (!horizontal
216 && !NILP (fullscreen) && !EQ (fullscreen, Qfullwidth)) 216 && !NILP (fullscreen) && !EQ (fullscreen, Qfullwidth))
217 || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)))); 217 || is_tty_frame (f))));
218} 218}
219 219
220 220
@@ -349,8 +349,6 @@ If FRAME is nil, use the selected frame.
349Return nil if the id has not been set. */) 349Return nil if the id has not been set. */)
350 (Lisp_Object frame) 350 (Lisp_Object frame)
351{ 351{
352 if (NILP (frame))
353 frame = selected_frame;
354 struct frame *f = decode_live_frame (frame); 352 struct frame *f = decode_live_frame (frame);
355 if (f->id == 0) 353 if (f->id == 0)
356 return Qnil; 354 return Qnil;
@@ -562,7 +560,7 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
562 560
563 /* Don't allow too small height of text-mode frames, or else cm.c 561 /* Don't allow too small height of text-mode frames, or else cm.c
564 might abort in cmcheckmagic. */ 562 might abort in cmcheckmagic. */
565 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal)) 563 if (is_tty_frame (f) && NILP (horizontal))
566 { 564 {
567 int min_height = (FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f) 565 int min_height = (FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)
568 + FRAME_WANTS_MODELINE_P (f) 566 + FRAME_WANTS_MODELINE_P (f)
@@ -1573,7 +1571,7 @@ make_terminal_frame (struct terminal *terminal, Lisp_Object parent,
1573 f->output_data.tty->display_info = &the_only_display_info; 1571 f->output_data.tty->display_info = &the_only_display_info;
1574 if (!inhibit_window_system 1572 if (!inhibit_window_system
1575 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame)) 1573 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
1576 || XFRAME (selected_frame)->output_method == output_msdos_raw)) 1574 || FRAME_MSDOS_P (XFRAME (selected_frame))))
1577 f->output_method = output_msdos_raw; 1575 f->output_method = output_msdos_raw;
1578 else 1576 else
1579 f->output_method = output_termcap; 1577 f->output_method = output_termcap;
@@ -1763,13 +1761,12 @@ affects all frames on the same terminal device. */)
1763 struct frame *sf = SELECTED_FRAME (); 1761 struct frame *sf = SELECTED_FRAME ();
1764 1762
1765#ifdef MSDOS 1763#ifdef MSDOS
1766 if (sf->output_method != output_msdos_raw 1764 if (!is_tty_frame (sf))
1767 && sf->output_method != output_termcap)
1768 emacs_abort (); 1765 emacs_abort ();
1769#else /* not MSDOS */ 1766#else /* not MSDOS */
1770 1767
1771#ifdef WINDOWSNT /* This should work now! */ 1768#ifdef WINDOWSNT /* This should work now! */
1772 if (sf->output_method != output_termcap) 1769 if (!FRAME_TERMCAP_P (sf))
1773 error ("Not using an ASCII terminal now; cannot make a new ASCII frame"); 1770 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
1774#endif 1771#endif
1775#endif /* not MSDOS */ 1772#endif /* not MSDOS */
@@ -1986,7 +1983,7 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1986 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf)) 1983 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
1987 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1); 1984 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
1988 1985
1989 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) 1986 if (is_tty_frame (f))
1990 { 1987 {
1991 struct tty_display_info *tty = FRAME_TTY (f); 1988 struct tty_display_info *tty = FRAME_TTY (f);
1992 Lisp_Object top_frame = tty->top_frame; 1989 Lisp_Object top_frame = tty->top_frame;
@@ -2800,7 +2797,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2800 && FRAME_LIVE_P (f1) 2797 && FRAME_LIVE_P (f1)
2801 && !FRAME_TOOLTIP_P (f1)) 2798 && !FRAME_TOOLTIP_P (f1))
2802 { 2799 {
2803 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1)) 2800 if (is_tty_frame (f1))
2804 { 2801 {
2805 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame; 2802 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
2806 2803
diff --git a/src/keyboard.c b/src/keyboard.c
index c63440059e5..3da42d61bad 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -2453,7 +2453,7 @@ read_decoded_event_from_main_queue (struct timespec *end_time,
2453#else 2453#else
2454 struct frame *frame = XFRAME (selected_frame); 2454 struct frame *frame = XFRAME (selected_frame);
2455 struct terminal *terminal = frame->terminal; 2455 struct terminal *terminal = frame->terminal;
2456 if (!((FRAME_TERMCAP_P (frame) || FRAME_MSDOS_P (frame)) 2456 if (!(is_tty_frame (frame)
2457 /* Don't apply decoding if we're just reading a raw event 2457 /* Don't apply decoding if we're just reading a raw event
2458 (e.g. reading bytes sent by the xterm to specify the position 2458 (e.g. reading bytes sent by the xterm to specify the position
2459 of a mouse click). */ 2459 of a mouse click). */
@@ -13032,7 +13032,7 @@ The elements of this list correspond to the arguments of
13032 13032
13033 Lisp_Object interrupt = interrupt_input ? Qt : Qnil; 13033 Lisp_Object interrupt = interrupt_input ? Qt : Qnil;
13034 Lisp_Object flow, meta; 13034 Lisp_Object flow, meta;
13035 if (FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf)) 13035 if (is_tty_frame (sf))
13036 { 13036 {
13037 flow = FRAME_TTY (sf)->flow_control ? Qt : Qnil; 13037 flow = FRAME_TTY (sf)->flow_control ? Qt : Qnil;
13038 meta = (FRAME_TTY (sf)->meta_key == 2 13038 meta = (FRAME_TTY (sf)->meta_key == 2
diff --git a/src/lisp.h b/src/lisp.h
index 05ea874a4bb..2081a45458f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -5754,7 +5754,7 @@ extern void *w32_daemon_event;
5754/* True if handling a fatal error already. */ 5754/* True if handling a fatal error already. */
5755extern bool fatal_error_in_progress; 5755extern bool fatal_error_in_progress;
5756 5756
5757/* True means don't do use window-system-specific display code. */ 5757/* True means don't use window-system-specific display code. */
5758extern bool inhibit_window_system; 5758extern bool inhibit_window_system;
5759/* True means that a filter or a sentinel is running. */ 5759/* True means that a filter or a sentinel is running. */
5760extern bool running_asynch_code; 5760extern bool running_asynch_code;
diff --git a/src/menu.c b/src/menu.c
index 747a87e9f3c..cb474a1b53e 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -405,8 +405,7 @@ single_menu_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy, void *sk
405 } 405 }
406 } 406 }
407 407
408 if ((FRAME_TERMCAP_P (XFRAME (Vmenu_updating_frame)) 408 if (is_tty_frame (XFRAME (Vmenu_updating_frame))
409 || FRAME_MSDOS_P (XFRAME (Vmenu_updating_frame)))
410 && !NILP (map)) 409 && !NILP (map))
411 /* Indicate visually that this is a submenu. */ 410 /* Indicate visually that this is a submenu. */
412 { 411 {
diff --git a/src/msdos.c b/src/msdos.c
index 7e89d549706..4d111b30969 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -1787,7 +1787,7 @@ internal_terminal_init (void)
1787#endif 1787#endif
1788 1788
1789 /* If this is the initial terminal, we are done here. */ 1789 /* If this is the initial terminal, we are done here. */
1790 if (sf->output_method == output_initial) 1790 if (FRAME_INITIAL_P (sf))
1791 return; 1791 return;
1792 1792
1793 internal_terminal 1793 internal_terminal
diff --git a/src/nsterm.m b/src/nsterm.m
index 118463a13c9..e186c16e725 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -72,6 +72,12 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
72#include "macfont.h" 72#include "macfont.h"
73#include <Carbon/Carbon.h> 73#include <Carbon/Carbon.h>
74#include <IOSurface/IOSurface.h> 74#include <IOSurface/IOSurface.h>
75/* ApplicationServices provides the macOS accessibility Zoom API
76 UAZoomEnabled and UAZoomChangeFocus (UniversalAccess framework).
77 Carbon.h already pulls in ApplicationServices on most SDK versions,
78 but the explicit import makes the dependency visible and guards
79 against SDK changes. */
80#import <ApplicationServices/ApplicationServices.h>
75#endif 81#endif
76 82
77static EmacsMenu *dockMenu; 83static EmacsMenu *dockMenu;
@@ -1086,6 +1092,126 @@ ns_update_begin (struct frame *f)
1086 [view lockFocus]; 1092 [view lockFocus];
1087} 1093}
1088 1094
1095/* --------------------------------------------------------------------------
1096 macOS Accessibility Zoom Support
1097 -------------------------------------------------------------------------- */
1098#ifdef NS_IMPL_COCOA
1099
1100static BOOL ns_is_UAZoomEnabled = NO;
1101static unsigned long ns_UAZoomEnabled_last_called_time_ns = 0;
1102static const unsigned long NS_UAZOOMENABLED_CACHE_INTERVAL_NS =
1103 (unsigned long)(500 * NSEC_PER_MSEC); /* 500ms. */
1104static NSTimeInterval NS_UAZOOMENABLED_DEFER_INTERVAL_SECS = 0.2; /* 200ms. */
1105static NSTimer *ns_deferred_UAZoomChangeFocus_timer = nil;
1106
1107static BOOL
1108ns_ua_zoom_enabled_p (void)
1109/* --------------------------------------------------------------------------
1110 Return the cached result of UAZoomEnabled. Refresh the cache every
1111 NS_UAZOOMENABLED_CACHE_INTERVAL_NS nanoseconds.
1112
1113 We cache the result to avoid the macOS Mach IPC Accessibility Server
1114 round trip cost on every Emacs cursor update. Since enabling Zoom
1115 requires an explicit user UI action that takes real user time, the
1116 cache TTL should be invisible to the user.
1117
1118 Use clock_gettime_nsec_np not CFAbsoluteTimeGetCurrent which depends
1119 on the wall clock which can be reset by the user or by NTP.
1120
1121 Main-thread-only and called from ns_update_end, below.
1122 -------------------------------------------------------------------------- */
1123{
1124 /* User-space equivalent to mach_absolute_time. */
1125 unsigned long now_ns = clock_gettime_nsec_np (CLOCK_UPTIME_RAW);
1126 if (now_ns - ns_UAZoomEnabled_last_called_time_ns
1127 > NS_UAZOOMENABLED_CACHE_INTERVAL_NS)
1128 {
1129 ns_is_UAZoomEnabled = UAZoomEnabled ();
1130 ns_UAZoomEnabled_last_called_time_ns = now_ns;
1131 }
1132 return ns_is_UAZoomEnabled;
1133}
1134
1135static inline CGRect
1136ns_cg_rect_flip_y (CGRect r)
1137/* --------------------------------------------------------------------------
1138 Convert a CGRect from Cocoa screen coordinates (origin at bottom-left
1139 of the primary display) to CoreGraphics coordinates (origin at
1140 top-left of the primary display). CoreGraphics defines its
1141 coordinate origin at the top-left corner of the primary display and
1142 all screens share this global coordinate space, so the flip always
1143 uses the primary display height regardless of which screen R is on.
1144 -------------------------------------------------------------------------- */
1145{
1146 CGDirectDisplayID mainID = CGMainDisplayID ();
1147 if (mainID == kCGNullDirectDisplay)
1148 return r;
1149 CGFloat primaryH = CGDisplayBounds (mainID).size.height;
1150 if (primaryH <= 0)
1151 return r;
1152 r.origin.y = primaryH - r.origin.y - r.size.height;
1153 return r;
1154}
1155
1156/* Cache cursor rects to call UAZoomChangeFocus only when the cursor
1157 position has changed, not merely when the cursor is blinking.
1158 See ns_draw_window_cursor and ns_update_end. */
1159static NSRect ns_UAZoom_cursor_rect_new;
1160static NSRect ns_UAZoom_cursor_rect_old;
1161
1162/* Track Zoom state per display cycle. Update the macOS Zoom cursor
1163 position when Zoom transitions to enabled. */
1164static BOOL ns_update_was_UAZoomEnabled = NO;
1165
1166static void
1167ns_UAZoomChangeFocus (EmacsView *view, BOOL force)
1168/* --------------------------------------------------------------------------
1169 Advise macOS Accessibility Zoom UAZoomChangeFocus of a potentially
1170 new cursor position. Force an updated position when Zoom transitions
1171 to enabled, or when the frame gets focus.
1172 -------------------------------------------------------------------------- */
1173{
1174 if (ns_ua_zoom_enabled_p ())
1175 {
1176 force = force || !ns_update_was_UAZoomEnabled;
1177 ns_update_was_UAZoomEnabled = YES;
1178 if (NSIsEmptyRect (ns_UAZoom_cursor_rect_new))
1179 return;
1180 if (force || !NSEqualRects (ns_UAZoom_cursor_rect_new,
1181 ns_UAZoom_cursor_rect_old))
1182 {
1183 ns_UAZoom_cursor_rect_old = ns_UAZoom_cursor_rect_new;
1184 NSRect windowRect = [view convertRect:ns_UAZoom_cursor_rect_new
1185 toView:nil];
1186 NSRect screenRect = [[view window] convertRectToScreen:windowRect];
1187 CGRect cgRect = ns_cg_rect_flip_y (NSRectToCGRect (screenRect));
1188 /* Some versions of macOS can ignore tiny rects, so we
1189 slightly expand a tiny one. Since we care mostly about its
1190 origin, this should be innocuous. */
1191 cgRect.size.width = MAX (cgRect.size.width, 6);
1192 cgRect.size.height = MAX (cgRect.size.height, 10);
1193 if (force)
1194 {
1195 /* UAZoomChangeFocus needs old and new cursor positions to
1196 be different, and also it sometimes needs a kick. In
1197 both cases, we fake a cursor move followed by the real
1198 cursor move. */
1199 CGRect cgRectJiggle = CGRectOffset (cgRect, 1.0, 1.0);
1200 if (UAZoomChangeFocus (&cgRectJiggle, NULL,
1201 kUAZoomFocusTypeInsertionPoint))
1202 NSLog (@"UAZoomChangeFocus jiggle failed");
1203 }
1204 if (UAZoomChangeFocus (&cgRect, NULL,
1205 kUAZoomFocusTypeInsertionPoint))
1206 NSLog (@"UAZoomChangeFocus failed");
1207 NSAccessibilityPostNotification
1208 (view, NSAccessibilityFocusedUIElementChangedNotification);
1209 }
1210 }
1211 else
1212 ns_update_was_UAZoomEnabled = NO;
1213}
1214#endif /* NS_IMPL_COCOA */
1089 1215
1090static void 1216static void
1091ns_update_end (struct frame *f) 1217ns_update_end (struct frame *f)
@@ -1108,6 +1234,10 @@ ns_update_end (struct frame *f)
1108 [[view window] flushWindow]; 1234 [[view window] flushWindow];
1109#endif 1235#endif
1110 1236
1237#ifdef NS_IMPL_COCOA
1238 ns_UAZoomChangeFocus (view, false);
1239#endif
1240
1111 unblock_input (); 1241 unblock_input ();
1112 ns_updating_frame = NULL; 1242 ns_updating_frame = NULL;
1113} 1243}
@@ -3238,6 +3368,16 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
3238 /* Prevent the cursor from being drawn outside the text area. */ 3368 /* Prevent the cursor from being drawn outside the text area. */
3239 r = NSIntersectionRect (r, ns_row_rect (w, glyph_row, TEXT_AREA)); 3369 r = NSIntersectionRect (r, ns_row_rect (w, glyph_row, TEXT_AREA));
3240 3370
3371#ifdef NS_IMPL_COCOA
3372 /* Cache the cursor rect for macOS Accessibility Zoom integration (see
3373 ns_update_end). Only store the rect for the active cursor ---
3374 inactive windows must not overwrite the value because redisplay may
3375 draw multiple windows per frame and the drawing order is not
3376 guaranteed. */
3377 if (active_p)
3378 ns_UAZoom_cursor_rect_new = r;
3379#endif
3380
3241 ns_focus (f, NULL, 0); 3381 ns_focus (f, NULL, 0);
3242 3382
3243 NSGraphicsContext *ctx = [NSGraphicsContext currentContext]; 3383 NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
@@ -6384,6 +6524,14 @@ ns_term_shutdown (int sig)
6384 } 6524 }
6385#endif 6525#endif
6386 6526
6527#ifdef NS_IMPL_COCOA
6528 /* Is accessibility enabled for this process/bundle? */
6529 if (AXIsProcessTrusted())
6530 NSLog (@"Emacs is macOS AXIsProcessTrusted");
6531 else
6532 NSLog (@"Emacs is not macOS AXIsProcessTrusted");
6533#endif
6534
6387 ns_send_appdefined (-2); 6535 ns_send_appdefined (-2);
6388} 6536}
6389 6537
@@ -7300,6 +7448,12 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
7300 return [self firstRectForCharacterRange: range]; 7448 return [self firstRectForCharacterRange: range];
7301} 7449}
7302 7450
7451- (NSRect)accessibilityFrame
7452{
7453 EmacsView *view = FRAME_NS_VIEW (*emacsframe);
7454 return [[view window] convertRectToScreen: ns_UAZoom_cursor_rect_new];
7455}
7456
7303#endif /* NS_IMPL_COCOA */ 7457#endif /* NS_IMPL_COCOA */
7304 7458
7305/*********************************************************************** 7459/***********************************************************************
@@ -8257,12 +8411,48 @@ ns_in_echo_area (void)
8257 ns_frame_rehighlight (*emacsframe); 8411 ns_frame_rehighlight (*emacsframe);
8258 [self adjustEmacsFrameRect]; 8412 [self adjustEmacsFrameRect];
8259 8413
8414#ifdef NS_IMPL_COCOA
8415 EmacsView *view = FRAME_NS_VIEW (*emacsframe);
8416 /* Make sure we have focus and the timer isn't already scheduled. */
8417 if (self.window.firstResponder == view
8418 && !ns_deferred_UAZoomChangeFocus_timer)
8419 {
8420 /* Calls to ns_UAZoomChangeFocus are synchronous. We defer the
8421 call to give macOS time to finish window compositing or the
8422 calls can be silently ignored by the Zoom daemon and with no
8423 errors reported. This also helps ensure ns_draw_window_cursor
8424 has populated ns_UAZoom_cursor_rect_new. The 200 ms delay was
8425 chosen as a balance between macOS headroom and user
8426 perception. */
8427 ns_deferred_UAZoomChangeFocus_timer
8428 = [[NSTimer
8429 scheduledTimerWithTimeInterval:
8430 NS_UAZOOMENABLED_DEFER_INTERVAL_SECS
8431 target: self
8432 selector:
8433 @selector (deferred_UAZoomChangeFocus_handler:)
8434 userInfo: 0
8435 repeats: NO]
8436 retain];
8437 }
8438#endif
8439
8260 event.kind = FOCUS_IN_EVENT; 8440 event.kind = FOCUS_IN_EVENT;
8261 XSETFRAME (event.frame_or_window, *emacsframe); 8441 XSETFRAME (event.frame_or_window, *emacsframe);
8262 kbd_buffer_store_event (&event); 8442 kbd_buffer_store_event (&event);
8263 ns_send_appdefined (-1); // Kick main loop 8443 ns_send_appdefined (-1); // Kick main loop
8264} 8444}
8265 8445
8446#ifdef NS_IMPL_COCOA
8447- (void)deferred_UAZoomChangeFocus_handler: (NSTimer *)timer
8448{
8449 EmacsView *view = FRAME_NS_VIEW (*emacsframe);
8450 ns_UAZoomChangeFocus (view, true);
8451 [ns_deferred_UAZoomChangeFocus_timer invalidate];
8452 [ns_deferred_UAZoomChangeFocus_timer release];
8453 ns_deferred_UAZoomChangeFocus_timer = nil;
8454}
8455#endif
8266 8456
8267- (void)windowDidResignKey: (NSNotification *)notification 8457- (void)windowDidResignKey: (NSNotification *)notification
8268/* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */ 8458/* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
@@ -8365,6 +8555,13 @@ ns_in_echo_area (void)
8365 8555
8366 FRAME_NS_VIEW (f) = self; 8556 FRAME_NS_VIEW (f) = self;
8367 *emacsframe = f; 8557 *emacsframe = f;
8558
8559#ifdef NS_IMPL_COCOA
8560 /* macOS Accessibility Zoom Support. */
8561 ns_UAZoom_cursor_rect_new = NSZeroRect;
8562 ns_UAZoom_cursor_rect_old = NSZeroRect;
8563#endif
8564
8368#ifdef NS_IMPL_COCOA 8565#ifdef NS_IMPL_COCOA
8369 old_title = 0; 8566 old_title = 0;
8370 maximizing_resize = NO; 8567 maximizing_resize = NO;
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index e0eb81bf81c..c1e00347343 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -703,33 +703,16 @@ pgtk_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
703 703
704static void 704static void
705pgtk_set_window_size (struct frame *f, bool change_gravity, 705pgtk_set_window_size (struct frame *f, bool change_gravity,
706 int width, int height) 706 int pixelwidth, int pixelheight)
707/* -------------------------------------------------------------------------- 707/* --------------------------------------------------------------------------
708 Adjust window pixel size based on given character grid size 708 Adjust window pixel size based on given width and height.
709 Impl is a bit more complex than other terms, need to do some
710 internal clipping.
711 -------------------------------------------------------------------------- */ 709 -------------------------------------------------------------------------- */
712{ 710{
713 int pixelwidth, pixelheight;
714
715 block_input (); 711 block_input ();
716 712
717 gtk_widget_get_size_request (FRAME_GTK_WIDGET (f), &pixelwidth,
718 &pixelheight);
719
720 pixelwidth = width;
721 pixelheight = height;
722
723 for (GtkWidget * w = FRAME_GTK_WIDGET (f); w != NULL;
724 w = gtk_widget_get_parent (w))
725 {
726 gint wd, hi;
727 gtk_widget_get_size_request (w, &wd, &hi);
728 }
729
730 f->output_data.pgtk->preferred_width = pixelwidth; 713 f->output_data.pgtk->preferred_width = pixelwidth;
731 f->output_data.pgtk->preferred_height = pixelheight; 714 f->output_data.pgtk->preferred_height = pixelheight;
732 xg_wm_set_size_hint (f, 0, 0); 715
733 xg_frame_set_char_size (f, pixelwidth, pixelheight); 716 xg_frame_set_char_size (f, pixelwidth, pixelheight);
734 gtk_widget_queue_resize (FRAME_WIDGET (f)); 717 gtk_widget_queue_resize (FRAME_WIDGET (f));
735 718
@@ -5722,10 +5705,11 @@ pgtk_focus_changed (gboolean is_enter, int state,
5722 5705
5723 /* Don't stop displaying the initial startup message 5706 /* Don't stop displaying the initial startup message
5724 for a switch-frame event we don't need. */ 5707 for a switch-frame event we don't need. */
5725 /* When run as a daemon, Vterminal_frame is always NIL. */ 5708 /* When run as a daemon, Vterminal_frame is always nil.
5709 FIXME: Isn't it actually the other way around? */
5726 bufp->ie.arg = (((NILP (Vterminal_frame) 5710 bufp->ie.arg = (((NILP (Vterminal_frame)
5727 || !FRAME_PGTK_P (XFRAME (Vterminal_frame)) 5711 || !FRAME_PGTK_P (XFRAME (Vterminal_frame))
5728 || EQ (Fdaemonp (), Qt)) 5712 || IS_DAEMON)
5729 && CONSP (Vframe_list) 5713 && CONSP (Vframe_list)
5730 && !NILP (XCDR (Vframe_list))) ? Qt : Qnil); 5714 && !NILP (XCDR (Vframe_list))) ? Qt : Qnil);
5731 bufp->ie.kind = FOCUS_IN_EVENT; 5715 bufp->ie.kind = FOCUS_IN_EVENT;
diff --git a/src/sysdep.c b/src/sysdep.c
index 8895655566e..10269e4d0ce 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -1341,8 +1341,7 @@ init_sys_modes (struct tty_display_info *tty_out)
1341 frame_garbaged = 1; 1341 frame_garbaged = 1;
1342 FOR_EACH_FRAME (tail, frame) 1342 FOR_EACH_FRAME (tail, frame)
1343 { 1343 {
1344 if ((FRAME_TERMCAP_P (XFRAME (frame)) 1344 if (is_tty_frame (XFRAME (frame))
1345 || FRAME_MSDOS_P (XFRAME (frame)))
1346 && FRAME_TTY (XFRAME (frame)) == tty_out) 1345 && FRAME_TTY (XFRAME (frame)) == tty_out)
1347 FRAME_GARBAGED_P (XFRAME (frame)) = 1; 1346 FRAME_GARBAGED_P (XFRAME (frame)) = 1;
1348 } 1347 }
diff --git a/src/term.c b/src/term.c
index afc36be434e..15be02c6514 100644
--- a/src/term.c
+++ b/src/term.c
@@ -2969,9 +2969,7 @@ Gpm-mouse can only be activated for one tty at a time. */)
2969 (void) 2969 (void)
2970{ 2970{
2971 struct frame *f = SELECTED_FRAME (); 2971 struct frame *f = SELECTED_FRAME ();
2972 struct tty_display_info *tty 2972 struct tty_display_info *tty = FRAME_TERMCAP_P (f) ? FRAME_TTY (f) : NULL;
2973 = ((f)->output_method == output_termcap
2974 ? (f)->terminal->display_info.tty : NULL);
2975 Gpm_Connect connection; 2973 Gpm_Connect connection;
2976 2974
2977 if (!tty) 2975 if (!tty)
@@ -3017,9 +3015,7 @@ DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
3017 (void) 3015 (void)
3018{ 3016{
3019 struct frame *f = SELECTED_FRAME (); 3017 struct frame *f = SELECTED_FRAME ();
3020 struct tty_display_info *tty 3018 struct tty_display_info *tty = FRAME_TERMCAP_P (f) ? FRAME_TTY (f) : NULL;
3021 = ((f)->output_method == output_termcap
3022 ? (f)->terminal->display_info.tty : NULL);
3023 3019
3024 if (!tty || gpm_tty != tty) 3020 if (!tty || gpm_tty != tty)
3025 return Qnil; /* Not activated on this terminal, nothing to do. */ 3021 return Qnil; /* Not activated on this terminal, nothing to do. */
@@ -4214,7 +4210,7 @@ tty_free_frame_resources (struct frame *f)
4214static void 4210static void
4215tty_free_frame_resources (struct frame *f) 4211tty_free_frame_resources (struct frame *f)
4216{ 4212{
4217 eassert (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)); 4213 eassert (is_tty_frame (f));
4218 free_frame_faces (f); 4214 free_frame_faces (f);
4219 /* Deleting a child frame means we have to thoroughly redisplay its 4215 /* Deleting a child frame means we have to thoroughly redisplay its
4220 root frame to make sure the child disappears from the display. */ 4216 root frame to make sure the child disappears from the display. */
diff --git a/src/terminal.c b/src/terminal.c
index 1b15d1f26be..5c4852c5b6f 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -251,8 +251,8 @@ decode_live_terminal (Lisp_Object terminal)
251 return t; 251 return t;
252} 252}
253 253
254/* Like decode_terminal, but ensure that the resulting terminal object refers 254/* Like decode_live_terminal, but ensure that the resulting terminal
255 to a text-based terminal device. */ 255 object refers to a text-based terminal device. */
256 256
257struct terminal * 257struct terminal *
258decode_tty_terminal (Lisp_Object terminal) 258decode_tty_terminal (Lisp_Object terminal)
@@ -508,6 +508,25 @@ return values. */)
508 } 508 }
509} 509}
510 510
511DEFUN ("frame-initial-p", Fframe_initial_p, Sframe_initial_p, 0, 1, 0,
512 doc: /* Return non-nil if FRAME is the initial frame.
513That is, the initial text frame used internally during daemon mode,
514batch mode, and the early stages of startup.
515If FRAME is a terminal object, return non-nil if it holds
516the initial frame. FRAME defaults to the selected frame. */)
517 (Lisp_Object frame)
518{
519 if (NILP (frame))
520 frame = selected_frame;
521 if (FRAMEP (frame))
522 {
523 struct frame *f = XFRAME (frame);
524 return FRAME_LIVE_P (f) && FRAME_INITIAL_P (f) ? Qt : Qnil;
525 }
526 struct terminal *t = decode_terminal (frame);
527 return t && t->type == output_initial ? Qt : Qnil;
528}
529
511DEFUN ("terminal-list", Fterminal_list, Sterminal_list, 0, 0, 0, 530DEFUN ("terminal-list", Fterminal_list, Sterminal_list, 0, 0, 0,
512 doc: /* Return a list of all terminal devices. */) 531 doc: /* Return a list of all terminal devices. */)
513 (void) 532 (void)
@@ -680,8 +699,6 @@ init_initial_terminal (void)
680#else 699#else
681 initial_terminal_lisp = make_lisp_ptr (create_terminal (output_initial, NULL), Lisp_Vectorlike); 700 initial_terminal_lisp = make_lisp_ptr (create_terminal (output_initial, NULL), Lisp_Vectorlike);
682#endif 701#endif
683 /* Note: menu-bar.el:menu-bar-update-buffers knows about this
684 special name of the initial terminal. */
685 initial_terminal->name = xstrdup ("initial_terminal"); 702 initial_terminal->name = xstrdup ("initial_terminal");
686 initial_terminal->kboard = initial_kboard; 703 initial_terminal->kboard = initial_kboard;
687 initial_terminal->delete_terminal_hook = &delete_initial_terminal; 704 initial_terminal->delete_terminal_hook = &delete_initial_terminal;
@@ -725,6 +742,7 @@ or some time later. */);
725 Vdelete_terminal_functions = Qnil; 742 Vdelete_terminal_functions = Qnil;
726 743
727 DEFSYM (Qterminal_live_p, "terminal-live-p"); 744 DEFSYM (Qterminal_live_p, "terminal-live-p");
745 DEFSYM (Qframe_initial_p, "frame-initial-p");
728 DEFSYM (Qdelete_terminal_functions, "delete-terminal-functions"); 746 DEFSYM (Qdelete_terminal_functions, "delete-terminal-functions");
729 DEFSYM (Qrun_hook_with_args, "run-hook-with-args"); 747 DEFSYM (Qrun_hook_with_args, "run-hook-with-args");
730 748
@@ -734,6 +752,7 @@ or some time later. */);
734 defsubr (&Sdelete_terminal); 752 defsubr (&Sdelete_terminal);
735 defsubr (&Sframe_terminal); 753 defsubr (&Sframe_terminal);
736 defsubr (&Sterminal_live_p); 754 defsubr (&Sterminal_live_p);
755 defsubr (&Sframe_initial_p);
737 defsubr (&Sterminal_list); 756 defsubr (&Sterminal_list);
738 defsubr (&Sterminal_name); 757 defsubr (&Sterminal_name);
739 defsubr (&Sterminal_parameters); 758 defsubr (&Sterminal_parameters);
diff --git a/src/w32xfns.c b/src/w32xfns.c
index f920e407343..df3d42c9d28 100644
--- a/src/w32xfns.c
+++ b/src/w32xfns.c
@@ -177,7 +177,7 @@ get_frame_dc (struct frame *f)
177 HGDIOBJ obj; 177 HGDIOBJ obj;
178 struct w32_output *output; 178 struct w32_output *output;
179 179
180 if (f->output_method != output_w32) 180 if (!FRAME_W32_P (f))
181 emacs_abort (); 181 emacs_abort ();
182 182
183 enter_crit (); 183 enter_crit ();
diff --git a/src/xdisp.c b/src/xdisp.c
index fd2ce49e031..3251750cd2a 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -13665,7 +13665,7 @@ clear_garbaged_frames (void)
13665 selected frame, and might leave the selected 13665 selected frame, and might leave the selected
13666 frame with corrupted display, if it happens not 13666 frame with corrupted display, if it happens not
13667 to be marked garbaged. */ 13667 to be marked garbaged. */
13668 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)))) 13668 && !(f != sf && is_tty_frame (f)))
13669 redraw_frame (f); 13669 redraw_frame (f);
13670 else 13670 else
13671 clear_current_matrices (f); 13671 clear_current_matrices (f);
@@ -16653,11 +16653,8 @@ hscroll_window_tree (Lisp_Object window)
16653 } 16653 }
16654 } 16654 }
16655 if (cursor_row->truncated_on_left_p) 16655 if (cursor_row->truncated_on_left_p)
16656 { 16656 /* On TTY frames, don't count the left truncation glyph. */
16657 /* On TTY frames, don't count the left truncation glyph. */ 16657 x_offset -= is_tty_frame (XFRAME (WINDOW_FRAME (w)));
16658 struct frame *f = XFRAME (WINDOW_FRAME (w));
16659 x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
16660 }
16661 16658
16662 text_area_width = window_box_width (w, TEXT_AREA); 16659 text_area_width = window_box_width (w, TEXT_AREA);
16663 16660
@@ -17391,7 +17388,7 @@ redisplay_internal (void)
17391 windows_or_buffers_changed = 47; 17388 windows_or_buffers_changed = 47;
17392 17389
17393 struct frame *previous_frame; 17390 struct frame *previous_frame;
17394 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf)) 17391 if (is_tty_frame (sf)
17395 && (previous_frame = FRAME_TTY (sf)->previous_frame, 17392 && (previous_frame = FRAME_TTY (sf)->previous_frame,
17396 previous_frame != sf)) 17393 previous_frame != sf))
17397 { 17394 {
@@ -17836,8 +17833,7 @@ redisplay_internal (void)
17836 } 17833 }
17837 17834
17838 retry_frame: 17835 retry_frame:
17839 if (FRAME_WINDOW_P (f) 17836 if (FRAME_WINDOW_P (f) || is_tty_frame (f) || f == sf)
17840 || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f) || f == sf)
17841 { 17837 {
17842 /* Only GC scrollbars when we redisplay the whole frame. */ 17838 /* Only GC scrollbars when we redisplay the whole frame. */
17843 bool gcscrollbars = f->redisplay || !REDISPLAY_SOME_P (); 17839 bool gcscrollbars = f->redisplay || !REDISPLAY_SOME_P ();
@@ -32864,6 +32860,8 @@ produce_special_glyphs (struct it *it, enum display_element_type what,
32864 /* Mirror for R2L. */ 32860 /* Mirror for R2L. */
32865 if (direction == R2L) 32861 if (direction == R2L)
32866 { 32862 {
32863 face_id = GLYPH_CODE_FACE (gc);
32864
32867 /* Try bidi mirroring first. */ 32865 /* Try bidi mirroring first. */
32868 int c = bidi_mirror_char (GLYPH_CODE_CHAR (gc)); 32866 int c = bidi_mirror_char (GLYPH_CODE_CHAR (gc));
32869 32867
@@ -32877,16 +32875,23 @@ produce_special_glyphs (struct it *it, enum display_element_type what,
32877 { 32875 {
32878 c = XFIXNUM (val); 32876 c = XFIXNUM (val);
32879 32877
32880 /* If something goes wrong defaults to '/'. */ 32878 /* If something goes wrong, fall back to '/'. */
32881 if (CHAR_VALID_P (c)) 32879 if (CHAR_VALID_P (c))
32882 SET_GLYPH (glyph, c, face_id); 32880 SET_GLYPH (glyph, c, face_id);
32883 else 32881 else
32884 SET_GLYPH (glyph, '/', face_id); 32882 SET_GLYPH (glyph, '/', face_id);
32885 } 32883 }
32884 else
32885 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
32886 } 32886 }
32887 else 32887 else
32888 {
32889 struct face *face = FACE_FROM_ID (it->f, face_id);
32890 int id = FACE_FOR_CHAR (it->f, face, c, -1, Qnil);
32891
32888 /* Bidi mirroring. */ 32892 /* Bidi mirroring. */
32889 SET_GLYPH (glyph, c, face_id); 32893 SET_GLYPH (glyph, c, id);
32894 }
32890 } 32895 }
32891 else 32896 else
32892 /* No mirroring. */ 32897 /* No mirroring. */
@@ -32925,6 +32930,8 @@ produce_special_glyphs (struct it *it, enum display_element_type what,
32925 if (((it->bidi_it.paragraph_dir == R2L) && !left_edge_p) || 32930 if (((it->bidi_it.paragraph_dir == R2L) && !left_edge_p) ||
32926 ((it->bidi_it.paragraph_dir == L2R) && left_edge_p)) 32931 ((it->bidi_it.paragraph_dir == L2R) && left_edge_p))
32927 { 32932 {
32933 face_id = GLYPH_CODE_FACE (gc);
32934
32928 /* Try bidi mirroring first. */ 32935 /* Try bidi mirroring first. */
32929 int c = bidi_mirror_char (GLYPH_CODE_CHAR (gc)); 32936 int c = bidi_mirror_char (GLYPH_CODE_CHAR (gc));
32930 32937
@@ -32938,12 +32945,14 @@ produce_special_glyphs (struct it *it, enum display_element_type what,
32938 { 32945 {
32939 c = XFIXNUM (val); 32946 c = XFIXNUM (val);
32940 32947
32941 /* If something goes wrong defaults to '$'. */ 32948 /* If something goes wrong, fall back to '$'. */
32942 if (CHAR_VALID_P (c)) 32949 if (CHAR_VALID_P (c))
32943 SET_GLYPH (glyph, c, face_id); 32950 SET_GLYPH (glyph, c, face_id);
32944 else 32951 else
32945 SET_GLYPH (glyph, '$', face_id); 32952 SET_GLYPH (glyph, '$', face_id);
32946 } 32953 }
32954 else
32955 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
32947 } 32956 }
32948 else 32957 else
32949 { 32958 {
diff --git a/src/xfaces.c b/src/xfaces.c
index 567a56d229c..fdc08391fb7 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -5827,7 +5827,7 @@ face for italic. */)
5827 } 5827 }
5828 5828
5829 /* Dispatch to the appropriate handler. */ 5829 /* Dispatch to the appropriate handler. */
5830 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) 5830 if (is_tty_frame (f))
5831 supports = tty_supports_face_attributes_p (f, attrs, def_face); 5831 supports = tty_supports_face_attributes_p (f, attrs, def_face);
5832#ifdef HAVE_WINDOW_SYSTEM 5832#ifdef HAVE_WINDOW_SYSTEM
5833 else 5833 else
@@ -6121,7 +6121,7 @@ realize_default_face (struct frame *f)
6121 ASET (lface, LFACE_FOREGROUND_INDEX, XCDR (color)); 6121 ASET (lface, LFACE_FOREGROUND_INDEX, XCDR (color));
6122 else if (FRAME_WINDOW_P (f)) 6122 else if (FRAME_WINDOW_P (f))
6123 return false; 6123 return false;
6124 else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) 6124 else if (FRAME_INITIAL_P (f) || is_tty_frame (f))
6125 ASET (lface, LFACE_FOREGROUND_INDEX, build_string (unspecified_fg)); 6125 ASET (lface, LFACE_FOREGROUND_INDEX, build_string (unspecified_fg));
6126 else 6126 else
6127 emacs_abort (); 6127 emacs_abort ();
@@ -6136,7 +6136,7 @@ realize_default_face (struct frame *f)
6136 ASET (lface, LFACE_BACKGROUND_INDEX, XCDR (color)); 6136 ASET (lface, LFACE_BACKGROUND_INDEX, XCDR (color));
6137 else if (FRAME_WINDOW_P (f)) 6137 else if (FRAME_WINDOW_P (f))
6138 return false; 6138 return false;
6139 else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) 6139 else if (FRAME_INITIAL_P (f) || is_tty_frame (f))
6140 ASET (lface, LFACE_BACKGROUND_INDEX, build_string (unspecified_bg)); 6140 ASET (lface, LFACE_BACKGROUND_INDEX, build_string (unspecified_bg));
6141 else 6141 else
6142 emacs_abort (); 6142 emacs_abort ();
@@ -6247,7 +6247,7 @@ realize_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE],
6247 6247
6248 if (FRAME_WINDOW_P (cache->f)) 6248 if (FRAME_WINDOW_P (cache->f))
6249 face = realize_gui_face (cache, attrs); 6249 face = realize_gui_face (cache, attrs);
6250 else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f)) 6250 else if (is_tty_frame (cache->f))
6251 face = realize_tty_face (cache, attrs); 6251 face = realize_tty_face (cache, attrs);
6252 else if (FRAME_INITIAL_P (cache->f)) 6252 else if (FRAME_INITIAL_P (cache->f))
6253 { 6253 {
@@ -6760,7 +6760,7 @@ realize_tty_face (struct face_cache *cache,
6760 struct frame *f = cache->f; 6760 struct frame *f = cache->f;
6761 6761
6762 /* Frame must be a termcap frame. */ 6762 /* Frame must be a termcap frame. */
6763 eassert (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f)); 6763 eassert (is_tty_frame (cache->f));
6764 6764
6765 /* Allocate a new realized face. */ 6765 /* Allocate a new realized face. */
6766 face = make_realized_face (attrs); 6766 face = make_realized_face (attrs);