aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPhilip Kaludercic2022-08-12 16:05:05 +0200
committerPhilip Kaludercic2022-08-12 16:05:05 +0200
commit1823349e6a61b2997b27cdb1ff42c69739693455 (patch)
treeed09268f8e57ab9196ff59df000c5f1268e09853 /src
parentfaa7f03b0c5b6d2c51bb185cf5a0f422ba0fb956 (diff)
parent829b131e5b3ad3b077be9d31215770b251341c68 (diff)
downloademacs-1823349e6a61b2997b27cdb1ff42c69739693455.tar.gz
emacs-1823349e6a61b2997b27cdb1ff42c69739693455.zip
Merge remote-tracking branch 'origin/master' into feature/package+vc
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in19
-rw-r--r--src/buffer.c5
-rw-r--r--src/bytecode.c4
-rw-r--r--src/callint.c118
-rw-r--r--src/callproc.c39
-rw-r--r--src/composite.c71
-rw-r--r--src/dispextern.h2
-rw-r--r--src/editfns.c54
-rw-r--r--src/eval.c71
-rw-r--r--src/frame.c6
-rw-r--r--src/ftcrfont.c8
-rw-r--r--src/haiku_support.cc33
-rw-r--r--src/haiku_support.h1
-rw-r--r--src/haikufns.c18
-rw-r--r--src/haikuterm.c88
-rw-r--r--src/haikuterm.h5
-rw-r--r--src/indent.c10
-rw-r--r--src/keyboard.c82
-rw-r--r--src/lisp.h11
-rw-r--r--src/lread.c160
-rw-r--r--src/marker.c5
-rw-r--r--src/nsfns.m1
-rw-r--r--src/pgtkfns.c1
-rw-r--r--src/print.c324
-rw-r--r--src/process.c156
-rw-r--r--src/process.h5
-rw-r--r--src/puresize.h2
-rw-r--r--src/sysdep.c5
-rw-r--r--src/timefns.c97
-rw-r--r--src/w32fns.c1
-rw-r--r--src/xdisp.c88
-rw-r--r--src/xfns.c87
-rw-r--r--src/xmenu.c26
-rw-r--r--src/xsettings.c7
-rw-r--r--src/xsettings.h2
-rw-r--r--src/xterm.c1373
-rw-r--r--src/xterm.h99
37 files changed, 2068 insertions, 1016 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index 7d15b7afd51..92a8790efdc 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -635,30 +635,23 @@ Emacs.pdmp: $(pdmp)
635endif 635endif
636 636
637ifeq ($(DUMPING),pdumper) 637ifeq ($(DUMPING),pdumper)
638$(pdmp): emacs$(EXEEXT) 638$(pdmp): emacs$(EXEEXT) $(lispsource)/loaddefs.el $(lispsource)/loaddefs.elc
639 LC_ALL=C $(RUN_TEMACS) -batch $(BUILD_DETAILS) -l loadup --temacs=pdump \ 639 LC_ALL=C $(RUN_TEMACS) -batch $(BUILD_DETAILS) -l loadup --temacs=pdump \
640 --bin-dest $(BIN_DESTDIR) --eln-dest $(ELN_DESTDIR) 640 --bin-dest $(BIN_DESTDIR) --eln-dest $(ELN_DESTDIR)
641 cp -f $@ $(bootstrap_pdmp) 641 cp -f $@ $(bootstrap_pdmp)
642endif 642endif
643 643
644## We run make-docfile twice because the command line may get too long
645## on some systems. Unfortunately, no-one has any idea
646## exactly how long the maximum safe command line length is on all the
647## various systems that Emacs supports.
648##
649## $(SOME_MACHINE_OBJECTS) comes before $(obj) because some files may 644## $(SOME_MACHINE_OBJECTS) comes before $(obj) because some files may
650## or may not be included in $(obj), but they are always included in 645## or may not be included in $(obj), but they are always included in
651## $(SOME_MACHINE_OBJECTS). Since a file is processed when it is mentioned 646## $(SOME_MACHINE_OBJECTS). Since a file is processed when it is mentioned
652## for the first time, this prevents any variation between configurations 647## for the first time, this prevents any variation between configurations
653## in the contents of the DOC file. 648## in the contents of the DOC file.
654## 649##
655$(etc)/DOC: $(libsrc)/make-docfile$(EXEEXT) $(doc_obj) $(lispsource)/loaddefs.el 650$(etc)/DOC: $(libsrc)/make-docfile$(EXEEXT) $(doc_obj)
656 $(AM_V_GEN)$(MKDIR_P) $(etc) 651 $(AM_V_GEN)$(MKDIR_P) $(etc)
657 $(AM_V_at)rm -f $(etc)/DOC 652 $(AM_V_at)rm -f $(etc)/DOC
658 $(AM_V_at)$(libsrc)/make-docfile -d $(srcdir) \ 653 $(AM_V_at)$(libsrc)/make-docfile -d $(srcdir) \
659 $(SOME_MACHINE_OBJECTS) $(doc_obj) > $(etc)/DOC 654 $(SOME_MACHINE_OBJECTS) $(doc_obj) > $(etc)/DOC
660 $(AM_V_at)$(libsrc)/make-docfile -a $(etc)/DOC -d $(lispsource) \
661 loaddefs.el
662 655
663$(libsrc)/make-docfile$(EXEEXT) $(libsrc)/make-fingerprint$(EXEEXT): \ 656$(libsrc)/make-docfile$(EXEEXT) $(libsrc)/make-fingerprint$(EXEEXT): \
664 $(lib)/libgnu.a 657 $(lib)/libgnu.a
@@ -888,13 +881,7 @@ elnlisp := $(addprefix ${lispsource}/,${elnlisp}) $(lisp:.elc=.eln)
888 fi 881 fi
889endif 882endif
890 883
891## VCSWITNESS points to the file that holds info about the current checkout. 884$(lispsource)/loaddefs.el: | bootstrap-emacs$(EXEEXT) $(bootstrap_pdmp)
892## We use it as a heuristic to decide when to rebuild loaddefs.el.
893## If empty it is ignored; the parent makefile can set it to some other value.
894VCSWITNESS =
895
896$(lispsource)/loaddefs.el: $(VCSWITNESS) | \
897 bootstrap-emacs$(EXEEXT) $(bootstrap_pdmp)
898 $(MAKE) -C ../lisp autoloads EMACS="$(bootstrap_exe)" 885 $(MAKE) -C ../lisp autoloads EMACS="$(bootstrap_exe)"
899 886
900## Dump an Emacs executable named bootstrap-emacs containing the 887## Dump an Emacs executable named bootstrap-emacs containing the
diff --git a/src/buffer.c b/src/buffer.c
index a07194aef72..e5601af5051 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -6431,12 +6431,15 @@ will run for `clone-indirect-buffer' calls as well. */);
6431 6431
6432 DEFVAR_LISP ("long-line-threshold", Vlong_line_threshold, 6432 DEFVAR_LISP ("long-line-threshold", Vlong_line_threshold,
6433 doc: /* Line length above which to use redisplay shortcuts. 6433 doc: /* Line length above which to use redisplay shortcuts.
6434
6434The value should be a positive integer or nil. 6435The value should be a positive integer or nil.
6435If the value is an integer, shortcuts in the display code intended 6436If the value is an integer, shortcuts in the display code intended
6436to speed up redisplay for long lines will automatically be enabled 6437to speed up redisplay for long lines will automatically be enabled
6437in buffers which contain one or more lines whose length is above 6438in buffers which contain one or more lines whose length is above
6438this threshold. 6439this threshold.
6439If nil, these display shortcuts will always remain disabled. */); 6440If nil, these display shortcuts will always remain disabled.
6441
6442There is no reason to change that value except for debugging purposes. */);
6440 XSETFASTINT (Vlong_line_threshold, 10000); 6443 XSETFASTINT (Vlong_line_threshold, 10000);
6441 6444
6442 defsubr (&Sbuffer_live_p); 6445 defsubr (&Sbuffer_live_p);
diff --git a/src/bytecode.c b/src/bytecode.c
index 2b1eccdc518..d75767bb0c5 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -1480,8 +1480,8 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
1480 1480
1481 CASE (Bnarrow_to_region): 1481 CASE (Bnarrow_to_region):
1482 { 1482 {
1483 Lisp_Object v2 = POP, v1 = POP; 1483 Lisp_Object v1 = POP;
1484 TOP = Fnarrow_to_region (TOP, v1, v2); 1484 TOP = Fnarrow_to_region (TOP, v1);
1485 NEXT; 1485 NEXT;
1486 } 1486 }
1487 1487
diff --git a/src/callint.c b/src/callint.c
index ffa3b231eb5..c974967459c 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -161,73 +161,33 @@ check_mark (bool for_region)
161 xsignal0 (Qmark_inactive); 161 xsignal0 (Qmark_inactive);
162} 162}
163 163
164/* If the list of args INPUT was produced with an explicit call to 164/* If FUNCTION has an `interactive-args' spec, replace relevant
165 `list', look for elements that were computed with 165 elements in VALUES with those forms instead.
166 (region-beginning) or (region-end), and put those expressions into
167 VALUES instead of the present values.
168 166
169 This function doesn't return a value because it modifies elements 167 This function doesn't return a value because it modifies elements
170 of VALUES to do its job. */ 168 of VALUES to do its job. */
171 169
172static void 170static void
173fix_command (Lisp_Object input, Lisp_Object function, Lisp_Object values) 171fix_command (Lisp_Object function, Lisp_Object values)
174{ 172{
175 /* FIXME: Instead of this ugly hack, we should provide a way for an 173 /* Quick exit if there's no values to alter. */
176 interactive spec to return an expression/function that will re-build the 174 if (!CONSP (values))
177 args without user intervention. */ 175 return;
178 if (CONSP (input)) 176
177 Lisp_Object reps = Fget (function, Qinteractive_args);
178
179 if (CONSP (reps))
179 { 180 {
180 Lisp_Object car; 181 int i = 0;
182 Lisp_Object vals = values;
181 183
182 car = XCAR (input); 184 while (!NILP (vals))
183 /* Skip through certain special forms. */
184 while (EQ (car, Qlet) || EQ (car, Qletx)
185 || EQ (car, Qsave_excursion)
186 || EQ (car, Qprogn))
187 { 185 {
188 while (CONSP (XCDR (input))) 186 Lisp_Object rep = Fassq (make_fixnum (i), reps);
189 input = XCDR (input); 187 if (!NILP (rep))
190 input = XCAR (input); 188 Fsetcar (vals, XCDR (rep));
191 if (!CONSP (input)) 189 vals = XCDR (vals);
192 break; 190 ++i;
193 car = XCAR (input);
194 }
195 if (EQ (car, Qlist))
196 {
197 Lisp_Object intail, valtail;
198 for (intail = Fcdr (input), valtail = values;
199 CONSP (valtail);
200 intail = Fcdr (intail), valtail = XCDR (valtail))
201 {
202 Lisp_Object elt;
203 elt = Fcar (intail);
204 if (CONSP (elt))
205 {
206 Lisp_Object presflag, carelt;
207 carelt = XCAR (elt);
208 /* If it is (if X Y), look at Y. */
209 if (EQ (carelt, Qif)
210 && NILP (Fnthcdr (make_fixnum (3), elt)))
211 elt = Fnth (make_fixnum (2), elt);
212 /* If it is (when ... Y), look at Y. */
213 else if (EQ (carelt, Qwhen))
214 {
215 while (CONSP (XCDR (elt)))
216 elt = XCDR (elt);
217 elt = Fcar (elt);
218 }
219
220 /* If the function call we're looking at
221 is a special preserved one, copy the
222 whole expression for this argument. */
223 if (CONSP (elt))
224 {
225 presflag = Fmemq (Fcar (elt), preserved_fns);
226 if (!NILP (presflag))
227 Fsetcar (valtail, Fcar (intail));
228 }
229 }
230 }
231 } 191 }
232 } 192 }
233 193
@@ -235,31 +195,28 @@ fix_command (Lisp_Object input, Lisp_Object function, Lisp_Object values)
235 optional, remove them from the list. This makes navigating the 195 optional, remove them from the list. This makes navigating the
236 history less confusing, since it doesn't contain a lot of 196 history less confusing, since it doesn't contain a lot of
237 parameters that aren't used. */ 197 parameters that aren't used. */
238 if (CONSP (values)) 198 Lisp_Object arity = Ffunc_arity (function);
199 /* We don't want to do this simplification if we have an &rest
200 function, because (cl-defun foo (a &optional (b 'zot)) ..)
201 etc. */
202 if (FIXNUMP (XCAR (arity)) && FIXNUMP (XCDR (arity)))
239 { 203 {
240 Lisp_Object arity = Ffunc_arity (function); 204 Lisp_Object final = Qnil;
241 /* We don't want to do this simplification if we have an &rest 205 ptrdiff_t final_i = 0, i = 0;
242 function, because (cl-defun foo (a &optional (b 'zot)) ..) 206 for (Lisp_Object tail = values;
243 etc. */ 207 CONSP (tail);
244 if (FIXNUMP (XCAR (arity)) && FIXNUMP (XCDR (arity))) 208 tail = XCDR (tail), ++i)
245 { 209 {
246 Lisp_Object final = Qnil; 210 if (!NILP (XCAR (tail)))
247 ptrdiff_t final_i = 0, i = 0;
248 for (Lisp_Object tail = values;
249 CONSP (tail);
250 tail = XCDR (tail), ++i)
251 { 211 {
252 if (!NILP (XCAR (tail))) 212 final = tail;
253 { 213 final_i = i;
254 final = tail;
255 final_i = i;
256 }
257 } 214 }
258
259 /* Chop the trailing optional values. */
260 if (final_i > 0 && final_i >= XFIXNUM (XCAR (arity)) - 1)
261 XSETCDR (final, Qnil);
262 } 215 }
216
217 /* Chop the trailing optional values. */
218 if (final_i > 0 && final_i >= XFIXNUM (XCAR (arity)) - 1)
219 XSETCDR (final, Qnil);
263 } 220 }
264} 221}
265 222
@@ -360,7 +317,6 @@ invoke it (via an `interactive' spec that contains, for instance, an
360 { 317 {
361 Lisp_Object funval = Findirect_function (function, Qt); 318 Lisp_Object funval = Findirect_function (function, Qt);
362 uintmax_t events = num_input_events; 319 uintmax_t events = num_input_events;
363 Lisp_Object input = specs;
364 /* Compute the arg values using the user's expression. */ 320 /* Compute the arg values using the user's expression. */
365 specs = Feval (specs, 321 specs = Feval (specs,
366 CONSP (funval) && EQ (Qclosure, XCAR (funval)) 322 CONSP (funval) && EQ (Qclosure, XCAR (funval))
@@ -371,7 +327,7 @@ invoke it (via an `interactive' spec that contains, for instance, an
371 Make a copy of the list of values, for the command history, 327 Make a copy of the list of values, for the command history,
372 and turn them into things we can eval. */ 328 and turn them into things we can eval. */
373 Lisp_Object values = quotify_args (Fcopy_sequence (specs)); 329 Lisp_Object values = quotify_args (Fcopy_sequence (specs));
374 fix_command (input, function, values); 330 fix_command (function, values);
375 call4 (intern ("add-to-history"), intern ("command-history"), 331 call4 (intern ("add-to-history"), intern ("command-history"),
376 Fcons (function, values), Qnil, Qt); 332 Fcons (function, values), Qnil, Qt);
377 } 333 }
@@ -950,4 +906,6 @@ use `event-start', `event-end', and `event-click-count'. */);
950 defsubr (&Scall_interactively); 906 defsubr (&Scall_interactively);
951 defsubr (&Sfuncall_interactively); 907 defsubr (&Sfuncall_interactively);
952 defsubr (&Sprefix_numeric_value); 908 defsubr (&Sprefix_numeric_value);
909
910 DEFSYM (Qinteractive_args, "interactive-args");
953} 911}
diff --git a/src/callproc.c b/src/callproc.c
index dd162f36a6c..e8e4c48b5be 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -650,7 +650,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
650 650
651 child_errno 651 child_errno
652 = emacs_spawn (&pid, filefd, fd_output, fd_error, new_argv, env, 652 = emacs_spawn (&pid, filefd, fd_output, fd_error, new_argv, env,
653 SSDATA (current_dir), NULL, &oldset); 653 SSDATA (current_dir), NULL, false, false, &oldset);
654 eassert ((child_errno == 0) == (0 < pid)); 654 eassert ((child_errno == 0) == (0 < pid));
655 655
656 if (pid > 0) 656 if (pid > 0)
@@ -1412,14 +1412,15 @@ emacs_posix_spawn_init_attributes (posix_spawnattr_t *attributes,
1412int 1412int
1413emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err, 1413emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1414 char **argv, char **envp, const char *cwd, 1414 char **argv, char **envp, const char *cwd,
1415 const char *pty, const sigset_t *oldset) 1415 const char *pty_name, bool pty_in, bool pty_out,
1416 const sigset_t *oldset)
1416{ 1417{
1417#if USABLE_POSIX_SPAWN 1418#if USABLE_POSIX_SPAWN
1418 /* Prefer the simpler `posix_spawn' if available. `posix_spawn' 1419 /* Prefer the simpler `posix_spawn' if available. `posix_spawn'
1419 doesn't yet support setting up pseudoterminals, so we fall back 1420 doesn't yet support setting up pseudoterminals, so we fall back
1420 to `vfork' if we're supposed to use a pseudoterminal. */ 1421 to `vfork' if we're supposed to use a pseudoterminal. */
1421 1422
1422 bool use_posix_spawn = pty == NULL; 1423 bool use_posix_spawn = pty_name == NULL;
1423 1424
1424 posix_spawn_file_actions_t actions; 1425 posix_spawn_file_actions_t actions;
1425 posix_spawnattr_t attributes; 1426 posix_spawnattr_t attributes;
@@ -1473,7 +1474,9 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1473 /* vfork, and prevent local vars from being clobbered by the vfork. */ 1474 /* vfork, and prevent local vars from being clobbered by the vfork. */
1474 pid_t *volatile newpid_volatile = newpid; 1475 pid_t *volatile newpid_volatile = newpid;
1475 const char *volatile cwd_volatile = cwd; 1476 const char *volatile cwd_volatile = cwd;
1476 const char *volatile pty_volatile = pty; 1477 const char *volatile ptyname_volatile = pty_name;
1478 bool volatile ptyin_volatile = pty_in;
1479 bool volatile ptyout_volatile = pty_out;
1477 char **volatile argv_volatile = argv; 1480 char **volatile argv_volatile = argv;
1478 int volatile stdin_volatile = std_in; 1481 int volatile stdin_volatile = std_in;
1479 int volatile stdout_volatile = std_out; 1482 int volatile stdout_volatile = std_out;
@@ -1485,7 +1488,7 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1485 /* Darwin doesn't let us run setsid after a vfork, so use fork when 1488 /* Darwin doesn't let us run setsid after a vfork, so use fork when
1486 necessary. Below, we reset SIGCHLD handling after a vfork, as 1489 necessary. Below, we reset SIGCHLD handling after a vfork, as
1487 apparently macOS can mistakenly deliver SIGCHLD to the child. */ 1490 apparently macOS can mistakenly deliver SIGCHLD to the child. */
1488 if (pty != NULL) 1491 if (pty_in || pty_out)
1489 pid = fork (); 1492 pid = fork ();
1490 else 1493 else
1491 pid = VFORK (); 1494 pid = VFORK ();
@@ -1495,7 +1498,9 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1495 1498
1496 newpid = newpid_volatile; 1499 newpid = newpid_volatile;
1497 cwd = cwd_volatile; 1500 cwd = cwd_volatile;
1498 pty = pty_volatile; 1501 pty_name = ptyname_volatile;
1502 pty_in = ptyin_volatile;
1503 pty_out = ptyout_volatile;
1499 argv = argv_volatile; 1504 argv = argv_volatile;
1500 std_in = stdin_volatile; 1505 std_in = stdin_volatile;
1501 std_out = stdout_volatile; 1506 std_out = stdout_volatile;
@@ -1506,13 +1511,12 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1506 if (pid == 0) 1511 if (pid == 0)
1507#endif /* not WINDOWSNT */ 1512#endif /* not WINDOWSNT */
1508 { 1513 {
1509 bool pty_flag = pty != NULL;
1510 /* Make the pty be the controlling terminal of the process. */ 1514 /* Make the pty be the controlling terminal of the process. */
1511#ifdef HAVE_PTYS 1515#ifdef HAVE_PTYS
1512 dissociate_controlling_tty (); 1516 dissociate_controlling_tty ();
1513 1517
1514 /* Make the pty's terminal the controlling terminal. */ 1518 /* Make the pty's terminal the controlling terminal. */
1515 if (pty_flag && std_in >= 0) 1519 if (pty_in && std_in >= 0)
1516 { 1520 {
1517#ifdef TIOCSCTTY 1521#ifdef TIOCSCTTY
1518 /* We ignore the return value 1522 /* We ignore the return value
@@ -1521,7 +1525,7 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1521#endif 1525#endif
1522 } 1526 }
1523#if defined (LDISC1) 1527#if defined (LDISC1)
1524 if (pty_flag && std_in >= 0) 1528 if (pty_in && std_in >= 0)
1525 { 1529 {
1526 struct termios t; 1530 struct termios t;
1527 tcgetattr (std_in, &t); 1531 tcgetattr (std_in, &t);
@@ -1531,7 +1535,7 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1531 } 1535 }
1532#else 1536#else
1533#if defined (NTTYDISC) && defined (TIOCSETD) 1537#if defined (NTTYDISC) && defined (TIOCSETD)
1534 if (pty_flag && std_in >= 0) 1538 if (pty_in && std_in >= 0)
1535 { 1539 {
1536 /* Use new line discipline. */ 1540 /* Use new line discipline. */
1537 int ldisc = NTTYDISC; 1541 int ldisc = NTTYDISC;
@@ -1548,18 +1552,21 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1548 both TIOCSCTTY is defined. */ 1552 both TIOCSCTTY is defined. */
1549 /* Now close the pty (if we had it open) and reopen it. 1553 /* Now close the pty (if we had it open) and reopen it.
1550 This makes the pty the controlling terminal of the subprocess. */ 1554 This makes the pty the controlling terminal of the subprocess. */
1551 if (pty_flag) 1555 if (pty_name)
1552 { 1556 {
1553 1557
1554 /* I wonder if emacs_close (emacs_open (pty, ...)) 1558 /* I wonder if emacs_close (emacs_open (pty, ...))
1555 would work? */ 1559 would work? */
1556 if (std_in >= 0) 1560 if (pty_in && std_in >= 0)
1557 emacs_close (std_in); 1561 emacs_close (std_in);
1558 std_out = std_in = emacs_open_noquit (pty, O_RDWR, 0); 1562 int ptyfd = emacs_open_noquit (pty_name, O_RDWR, 0);
1559 1563 if (pty_in)
1564 std_in = ptyfd;
1565 if (pty_out)
1566 std_out = ptyfd;
1560 if (std_in < 0) 1567 if (std_in < 0)
1561 { 1568 {
1562 emacs_perror (pty); 1569 emacs_perror (pty_name);
1563 _exit (EXIT_CANCELED); 1570 _exit (EXIT_CANCELED);
1564 } 1571 }
1565 1572
@@ -1599,7 +1606,7 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1599 /* Stop blocking SIGCHLD in the child. */ 1606 /* Stop blocking SIGCHLD in the child. */
1600 unblock_child_signal (oldset); 1607 unblock_child_signal (oldset);
1601 1608
1602 if (pty_flag) 1609 if (pty_out)
1603 child_setup_tty (std_out); 1610 child_setup_tty (std_out);
1604#endif 1611#endif
1605 1612
diff --git a/src/composite.c b/src/composite.c
index 0f90b92a785..22422cca090 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -24,6 +24,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
24 24
25#include <config.h> 25#include <config.h>
26 26
27#include <stdlib.h> /* for qsort */
28
27#include "lisp.h" 29#include "lisp.h"
28#include "character.h" 30#include "character.h"
29#include "composite.h" 31#include "composite.h"
@@ -1021,7 +1023,11 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
1021 /* But we don't know where to stop the searching. */ 1023 /* But we don't know where to stop the searching. */
1022 endpos = NILP (string) ? BEGV - 1 : -1; 1024 endpos = NILP (string) ? BEGV - 1 : -1;
1023 /* Usually we don't reach ENDPOS because we stop searching 1025 /* Usually we don't reach ENDPOS because we stop searching
1024 at an uncomposable character (NL, LRE, etc). */ 1026 at an uncomposable character (NL, LRE, etc). In buffers
1027 with long lines, however, NL might be far away, so
1028 pretend that the buffer is smaller. */
1029 if (current_buffer->long_line_optimizations_p)
1030 endpos = get_closer_narrowed_begv (cmp_it->parent_it->w, charpos);
1025 } 1031 }
1026 } 1032 }
1027 cmp_it->id = -1; 1033 cmp_it->id = -1;
@@ -1580,7 +1586,6 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, ptrdiff_t backlim,
1580 Lisp_Object window; 1586 Lisp_Object window;
1581 struct window *w; 1587 struct window *w;
1582 bool need_adjustment = 0; 1588 bool need_adjustment = 0;
1583 ptrdiff_t narrowed_begv;
1584 1589
1585 window = Fget_buffer_window (Fcurrent_buffer (), Qnil); 1590 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
1586 if (NILP (window)) 1591 if (NILP (window))
@@ -1597,11 +1602,14 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, ptrdiff_t backlim,
1597 } 1602 }
1598 else 1603 else
1599 head = backlim; 1604 head = backlim;
1600 /* In buffers with very long lines, this function becomes very 1605 if (current_buffer->long_line_optimizations_p)
1601 slow. Pretend that the buffer is narrowed to make it fast. */ 1606 {
1602 narrowed_begv = get_narrowed_begv (w, window_point (w)); 1607 /* In buffers with very long lines, this function becomes very
1603 if (narrowed_begv && pos > narrowed_begv) 1608 slow. Pretend that the buffer is narrowed to make it fast. */
1604 head = narrowed_begv; 1609 ptrdiff_t begv = get_closer_narrowed_begv (w, window_point (w));
1610 if (pos > begv)
1611 head = begv;
1612 }
1605 tail = ZV; 1613 tail = ZV;
1606 stop = GPT; 1614 stop = GPT;
1607 cur.pos_byte = CHAR_TO_BYTE (cur.pos); 1615 cur.pos_byte = CHAR_TO_BYTE (cur.pos);
@@ -2048,6 +2056,54 @@ See `find-composition' for more details. */)
2048 return Fcons (make_fixnum (start), Fcons (make_fixnum (end), tail)); 2056 return Fcons (make_fixnum (start), Fcons (make_fixnum (end), tail));
2049} 2057}
2050 2058
2059static int
2060compare_composition_rules (const void *r1, const void *r2)
2061{
2062 Lisp_Object vec1 = *(Lisp_Object *)r1, vec2 = *(Lisp_Object *)r2;
2063
2064 return XFIXNAT (AREF (vec2, 1)) - XFIXNAT (AREF (vec1, 1));
2065}
2066
2067DEFUN ("composition-sort-rules", Fcomposition_sort_rules,
2068 Scomposition_sort_rules, 1, 1, 0,
2069 doc: /* Sort composition RULES by their LOOKBACK parameter.
2070
2071If RULES include just one rule, return RULES.
2072Otherwise, return a new list of rules where all the rules are
2073arranged in decreasing order of the LOOKBACK parameter of the
2074rules (the second element of the rule's vector). This is required
2075when combining composition rules from different sources, because
2076of the way buffer text is examined for matching one of the rules. */)
2077 (Lisp_Object rules)
2078{
2079 ptrdiff_t nrules;
2080 USE_SAFE_ALLOCA;
2081
2082 CHECK_LIST (rules);
2083 nrules = list_length (rules);
2084 if (nrules > 1)
2085 {
2086 ptrdiff_t i;
2087 Lisp_Object *sortvec;
2088
2089 SAFE_NALLOCA (sortvec, 1, nrules);
2090 for (i = 0; i < nrules; i++)
2091 {
2092 Lisp_Object elt = XCAR (rules);
2093 if (VECTORP (elt) && ASIZE (elt) == 3 && FIXNATP (AREF (elt, 1)))
2094 sortvec[i] = elt;
2095 else
2096 error ("Invalid composition rule in RULES argument");
2097 rules = XCDR (rules);
2098 }
2099 qsort (sortvec, nrules, sizeof (Lisp_Object), compare_composition_rules);
2100 rules = Flist (nrules, sortvec);
2101 SAFE_FREE ();
2102 }
2103
2104 return rules;
2105}
2106
2051 2107
2052void 2108void
2053syms_of_composite (void) 2109syms_of_composite (void)
@@ -2179,4 +2235,5 @@ This list is auto-generated, you should not need to modify it. */);
2179 defsubr (&Sfind_composition_internal); 2235 defsubr (&Sfind_composition_internal);
2180 defsubr (&Scomposition_get_gstring); 2236 defsubr (&Scomposition_get_gstring);
2181 defsubr (&Sclear_composition_cache); 2237 defsubr (&Sclear_composition_cache);
2238 defsubr (&Scomposition_sort_rules);
2182} 2239}
diff --git a/src/dispextern.h b/src/dispextern.h
index 037e02ff58f..12ba927261f 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2287,6 +2287,8 @@ struct composition_it
2287 reverse order, and thus the grapheme clusters must be rendered 2287 reverse order, and thus the grapheme clusters must be rendered
2288 from the last to the first. */ 2288 from the last to the first. */
2289 bool reversed_p; 2289 bool reversed_p;
2290 /* Parent iterator. */
2291 struct it *parent_it;
2290 2292
2291 /** The following members contain information about the current 2293 /** The following members contain information about the current
2292 grapheme cluster. */ 2294 grapheme cluster. */
diff --git a/src/editfns.c b/src/editfns.c
index 79af27d24da..07f5c0bbef7 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -2660,9 +2660,11 @@ DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
2660 doc: /* Remove restrictions (narrowing) from current buffer. 2660 doc: /* Remove restrictions (narrowing) from current buffer.
2661This allows the buffer's full text to be seen and edited. 2661This allows the buffer's full text to be seen and edited.
2662 2662
2663When called from Lisp inside a body form in which `narrow-to-region' 2663Note that, when the current buffer contains one or more lines whose
2664was called with an optional argument LOCK non-nil, this function does 2664length is above `long-line-threshold', Emacs may decide to leave, for
2665not produce any effect. */) 2665performance reasons, the accessible portion of the buffer unchanged
2666after this function is called from low-level hooks, such as
2667`jit-lock-functions' or `post-command-hook'. */)
2666 (void) 2668 (void)
2667{ 2669{
2668 if (! NILP (Vrestrictions_locked)) 2670 if (! NILP (Vrestrictions_locked))
@@ -2689,22 +2691,11 @@ unwind_locked_zv (Lisp_Object point_max)
2689 SET_BUF_ZV (current_buffer, XFIXNUM (point_max)); 2691 SET_BUF_ZV (current_buffer, XFIXNUM (point_max));
2690} 2692}
2691 2693
2692DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 3, "r", 2694/* Internal function for Fnarrow_to_region, meant to be used with a
2693 doc: /* Restrict editing in this buffer to the current region. 2695 third argument 'true', in which case it should be followed by "specbind
2694The rest of the text becomes temporarily invisible and untouchable 2696 (Qrestrictions_locked, Qt)". */
2695but is not deleted; if you save the buffer in a file, the invisible 2697Lisp_Object
2696text is included in the file. \\[widen] makes all visible again. 2698narrow_to_region_internal (Lisp_Object start, Lisp_Object end, bool lock)
2697See also `save-restriction'.
2698
2699When calling from Lisp, pass two arguments START and END:
2700positions (integers or markers) bounding the text that should
2701remain visible.
2702
2703When called from Lisp with the optional argument LOCK non-nil,
2704calls to `widen', or to `narrow-to-region' with an optional
2705argument LOCK nil, do not produce any effect until the end of
2706the current body form. */)
2707 (Lisp_Object start, Lisp_Object end, Lisp_Object lock)
2708{ 2699{
2709 EMACS_INT s = fix_position (start), e = fix_position (end); 2700 EMACS_INT s = fix_position (start), e = fix_position (end);
2710 2701
@@ -2713,7 +2704,7 @@ the current body form. */)
2713 EMACS_INT tem = s; s = e; e = tem; 2704 EMACS_INT tem = s; s = e; e = tem;
2714 } 2705 }
2715 2706
2716 if (! NILP (lock)) 2707 if (lock)
2717 { 2708 {
2718 if (!(BEGV <= s && s <= e && e <= ZV)) 2709 if (!(BEGV <= s && s <= e && e <= ZV))
2719 args_out_of_range (start, end); 2710 args_out_of_range (start, end);
@@ -2727,8 +2718,6 @@ the current body form. */)
2727 2718
2728 SET_BUF_BEGV (current_buffer, s); 2719 SET_BUF_BEGV (current_buffer, s);
2729 SET_BUF_ZV (current_buffer, e); 2720 SET_BUF_ZV (current_buffer, e);
2730
2731 specbind (Qrestrictions_locked, Qt);
2732 } 2721 }
2733 else 2722 else
2734 { 2723 {
@@ -2754,6 +2743,27 @@ the current body form. */)
2754 return Qnil; 2743 return Qnil;
2755} 2744}
2756 2745
2746DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 2, "r",
2747 doc: /* Restrict editing in this buffer to the current region.
2748The rest of the text becomes temporarily invisible and untouchable
2749but is not deleted; if you save the buffer in a file, the invisible
2750text is included in the file. \\[widen] makes all visible again.
2751See also `save-restriction'.
2752
2753When calling from Lisp, pass two arguments START and END:
2754positions (integers or markers) bounding the text that should
2755remain visible.
2756
2757Note that, when the current buffer contains one or more lines whose
2758length is above `long-line-threshold', Emacs may decide to leave, for
2759performance reasons, the accessible portion of the buffer unchanged
2760after this function is called from low-level hooks, such as
2761`jit-lock-functions' or `post-command-hook'. */)
2762 (Lisp_Object start, Lisp_Object end)
2763{
2764 return narrow_to_region_internal (start, end, false);
2765}
2766
2757Lisp_Object 2767Lisp_Object
2758save_restriction_save (void) 2768save_restriction_save (void)
2759{ 2769{
diff --git a/src/eval.c b/src/eval.c
index 141d2546f08..56b42966623 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -57,6 +57,12 @@ Lisp_Object Vrun_hooks;
57/* FIXME: We should probably get rid of this! */ 57/* FIXME: We should probably get rid of this! */
58Lisp_Object Vsignaling_function; 58Lisp_Object Vsignaling_function;
59 59
60/* The handler structure which will catch errors in Lisp hooks called
61 from redisplay. We do not use it for this; we compare it with the
62 handler which is about to be used in signal_or_quit, and if it
63 matches, cause a backtrace to be generated. */
64static struct handler *redisplay_deep_handler;
65
60/* These would ordinarily be static, but they need to be visible to GDB. */ 66/* These would ordinarily be static, but they need to be visible to GDB. */
61bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE; 67bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE;
62Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE; 68Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE;
@@ -246,6 +252,7 @@ init_eval (void)
246 lisp_eval_depth = 0; 252 lisp_eval_depth = 0;
247 /* This is less than the initial value of num_nonmacro_input_events. */ 253 /* This is less than the initial value of num_nonmacro_input_events. */
248 when_entered_debugger = -1; 254 when_entered_debugger = -1;
255 redisplay_deep_handler = NULL;
249} 256}
250 257
251/* Ensure that *M is at least A + B if possible, or is its maximum 258/* Ensure that *M is at least A + B if possible, or is its maximum
@@ -333,7 +340,8 @@ call_debugger (Lisp_Object arg)
333 /* Interrupting redisplay and resuming it later is not safe under 340 /* Interrupting redisplay and resuming it later is not safe under
334 all circumstances. So, when the debugger returns, abort the 341 all circumstances. So, when the debugger returns, abort the
335 interrupted redisplay by going back to the top-level. */ 342 interrupted redisplay by going back to the top-level. */
336 if (debug_while_redisplaying) 343 if (debug_while_redisplaying
344 && !EQ (Vdebugger, Qdebug_early))
337 Ftop_level (); 345 Ftop_level ();
338 346
339 return unbind_to (count, val); 347 return unbind_to (count, val);
@@ -593,16 +601,19 @@ The return value is BASE-VARIABLE. */)
593 601
594 if (SYMBOL_CONSTANT_P (new_alias)) 602 if (SYMBOL_CONSTANT_P (new_alias))
595 /* Making it an alias effectively changes its value. */ 603 /* Making it an alias effectively changes its value. */
596 error ("Cannot make a constant an alias"); 604 error ("Cannot make a constant an alias: %s",
605 SDATA (SYMBOL_NAME (new_alias)));
597 606
598 sym = XSYMBOL (new_alias); 607 sym = XSYMBOL (new_alias);
599 608
600 switch (sym->u.s.redirect) 609 switch (sym->u.s.redirect)
601 { 610 {
602 case SYMBOL_FORWARDED: 611 case SYMBOL_FORWARDED:
603 error ("Cannot make an internal variable an alias"); 612 error ("Cannot make a built-in variable an alias: %s",
613 SDATA (SYMBOL_NAME (new_alias)));
604 case SYMBOL_LOCALIZED: 614 case SYMBOL_LOCALIZED:
605 error ("Don't know how to make a localized variable an alias"); 615 error ("Don't know how to make a buffer-local variable an alias: %s",
616 SDATA (SYMBOL_NAME (new_alias)));
606 case SYMBOL_PLAINVAL: 617 case SYMBOL_PLAINVAL:
607 case SYMBOL_VARALIAS: 618 case SYMBOL_VARALIAS:
608 break; 619 break;
@@ -633,7 +644,8 @@ The return value is BASE-VARIABLE. */)
633 for (p = specpdl_ptr; p > specpdl; ) 644 for (p = specpdl_ptr; p > specpdl; )
634 if ((--p)->kind >= SPECPDL_LET 645 if ((--p)->kind >= SPECPDL_LET
635 && (EQ (new_alias, specpdl_symbol (p)))) 646 && (EQ (new_alias, specpdl_symbol (p))))
636 error ("Don't know how to make a let-bound variable an alias"); 647 error ("Don't know how to make a let-bound variable an alias: %s",
648 SDATA (SYMBOL_NAME (new_alias)));
637 } 649 }
638 650
639 if (sym->u.s.trapped_write == SYMBOL_TRAPPED_WRITE) 651 if (sym->u.s.trapped_write == SYMBOL_TRAPPED_WRITE)
@@ -1552,12 +1564,16 @@ internal_condition_case_n (Lisp_Object (*bfun) (ptrdiff_t, Lisp_Object *),
1552 ptrdiff_t nargs, 1564 ptrdiff_t nargs,
1553 Lisp_Object *args)) 1565 Lisp_Object *args))
1554{ 1566{
1567 struct handler *old_deep = redisplay_deep_handler;
1555 struct handler *c = push_handler (handlers, CONDITION_CASE); 1568 struct handler *c = push_handler (handlers, CONDITION_CASE);
1569 if (redisplaying_p)
1570 redisplay_deep_handler = c;
1556 if (sys_setjmp (c->jmp)) 1571 if (sys_setjmp (c->jmp))
1557 { 1572 {
1558 Lisp_Object val = handlerlist->val; 1573 Lisp_Object val = handlerlist->val;
1559 clobbered_eassert (handlerlist == c); 1574 clobbered_eassert (handlerlist == c);
1560 handlerlist = handlerlist->next; 1575 handlerlist = handlerlist->next;
1576 redisplay_deep_handler = old_deep;
1561 return hfun (val, nargs, args); 1577 return hfun (val, nargs, args);
1562 } 1578 }
1563 else 1579 else
@@ -1565,6 +1581,7 @@ internal_condition_case_n (Lisp_Object (*bfun) (ptrdiff_t, Lisp_Object *),
1565 Lisp_Object val = bfun (nargs, args); 1581 Lisp_Object val = bfun (nargs, args);
1566 eassert (handlerlist == c); 1582 eassert (handlerlist == c);
1567 handlerlist = c->next; 1583 handlerlist = c->next;
1584 redisplay_deep_handler = old_deep;
1568 return val; 1585 return val;
1569 } 1586 }
1570} 1587}
@@ -1697,6 +1714,11 @@ quit (void)
1697 return signal_or_quit (Qquit, Qnil, true); 1714 return signal_or_quit (Qquit, Qnil, true);
1698} 1715}
1699 1716
1717/* Has an error in redisplay giving rise to a backtrace occurred as
1718 yet in the current command? This gets reset in the command
1719 loop. */
1720bool backtrace_yet = false;
1721
1700/* Signal an error, or quit. ERROR_SYMBOL and DATA are as with Fsignal. 1722/* Signal an error, or quit. ERROR_SYMBOL and DATA are as with Fsignal.
1701 If KEYBOARD_QUIT, this is a quit; ERROR_SYMBOL should be 1723 If KEYBOARD_QUIT, this is a quit; ERROR_SYMBOL should be
1702 Qquit and DATA should be Qnil, and this function may return. 1724 Qquit and DATA should be Qnil, and this function may return.
@@ -1812,6 +1834,40 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
1812 unbind_to (count, Qnil); 1834 unbind_to (count, Qnil);
1813 } 1835 }
1814 1836
1837 /* If an error is signalled during a Lisp hook in redisplay, write a
1838 backtrace into the buffer *Redisplay-trace*. */
1839 if (!debugger_called && !NILP (error_symbol)
1840 && backtrace_on_redisplay_error
1841 && (NILP (clause) || h == redisplay_deep_handler)
1842 && NILP (Vinhibit_debugger)
1843 && !NILP (Ffboundp (Qdebug_early)))
1844 {
1845 max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
1846 specpdl_ref count = SPECPDL_INDEX ();
1847 ptrdiff_t counti = specpdl_ref_to_count (count);
1848 AUTO_STRING (redisplay_trace, "*Redisplay_trace*");
1849 Lisp_Object redisplay_trace_buffer;
1850 AUTO_STRING (gap, "\n\n\n\n"); /* Separates things in *Redisplay-trace* */
1851 Lisp_Object delayed_warning;
1852 max_ensure_room (&max_specpdl_size, counti, 200);
1853 redisplay_trace_buffer = Fget_buffer_create (redisplay_trace, Qnil);
1854 current_buffer = XBUFFER (redisplay_trace_buffer);
1855 if (!backtrace_yet) /* Are we on the first backtrace of the command? */
1856 Ferase_buffer ();
1857 else
1858 Finsert (1, &gap);
1859 backtrace_yet = true;
1860 specbind (Qstandard_output, redisplay_trace_buffer);
1861 specbind (Qdebugger, Qdebug_early);
1862 call_debugger (list2 (Qerror, Fcons (error_symbol, data)));
1863 unbind_to (count, Qnil);
1864 delayed_warning = make_string
1865 ("Error in a redisplay Lisp hook. See buffer *Redisplay_trace*", 61);
1866
1867 Vdelayed_warnings_list = Fcons (list2 (Qerror, delayed_warning),
1868 Vdelayed_warnings_list);
1869 }
1870
1815 if (!NILP (clause)) 1871 if (!NILP (clause))
1816 { 1872 {
1817 Lisp_Object unwind_data 1873 Lisp_Object unwind_data
@@ -4274,6 +4330,11 @@ Does not apply if quit is handled by a `condition-case'. */);
4274 DEFVAR_BOOL ("debug-on-next-call", debug_on_next_call, 4330 DEFVAR_BOOL ("debug-on-next-call", debug_on_next_call,
4275 doc: /* Non-nil means enter debugger before next `eval', `apply' or `funcall'. */); 4331 doc: /* Non-nil means enter debugger before next `eval', `apply' or `funcall'. */);
4276 4332
4333 DEFVAR_BOOL ("backtrace-on-redisplay-error", backtrace_on_redisplay_error,
4334 doc: /* Non-nil means create a backtrace if a lisp error occurs in redisplay.
4335The backtrace is written to buffer *Redisplay-trace*. */);
4336 backtrace_on_redisplay_error = false;
4337
4277 DEFVAR_BOOL ("debugger-may-continue", debugger_may_continue, 4338 DEFVAR_BOOL ("debugger-may-continue", debugger_may_continue,
4278 doc: /* Non-nil means debugger may continue execution. 4339 doc: /* Non-nil means debugger may continue execution.
4279This is nil when the debugger is called under circumstances where it 4340This is nil when the debugger is called under circumstances where it
diff --git a/src/frame.c b/src/frame.c
index a39e1c4944f..25d71e0769f 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3916,9 +3916,10 @@ static const struct frame_parm_table frame_parms[] =
3916 {"z-group", SYMBOL_INDEX (Qz_group)}, 3916 {"z-group", SYMBOL_INDEX (Qz_group)},
3917 {"override-redirect", SYMBOL_INDEX (Qoverride_redirect)}, 3917 {"override-redirect", SYMBOL_INDEX (Qoverride_redirect)},
3918 {"no-special-glyphs", SYMBOL_INDEX (Qno_special_glyphs)}, 3918 {"no-special-glyphs", SYMBOL_INDEX (Qno_special_glyphs)},
3919 {"alpha-background", SYMBOL_INDEX (Qalpha_background)}, 3919 {"alpha-background", SYMBOL_INDEX (Qalpha_background)},
3920 {"use-frame-synchronization", SYMBOL_INDEX (Quse_frame_synchronization)},
3920#ifdef HAVE_X_WINDOWS 3921#ifdef HAVE_X_WINDOWS
3921 {"shaded", SYMBOL_INDEX (Qshaded)}, 3922 {"shaded", SYMBOL_INDEX (Qshaded)},
3922#endif 3923#endif
3923#ifdef NS_IMPL_COCOA 3924#ifdef NS_IMPL_COCOA
3924 {"ns-appearance", SYMBOL_INDEX (Qns_appearance)}, 3925 {"ns-appearance", SYMBOL_INDEX (Qns_appearance)},
@@ -6195,6 +6196,7 @@ syms_of_frame (void)
6195 DEFSYM (Qtop_only, "top-only"); 6196 DEFSYM (Qtop_only, "top-only");
6196 DEFSYM (Qiconify_top_level, "iconify-top-level"); 6197 DEFSYM (Qiconify_top_level, "iconify-top-level");
6197 DEFSYM (Qmake_invisible, "make-invisible"); 6198 DEFSYM (Qmake_invisible, "make-invisible");
6199 DEFSYM (Quse_frame_synchronization, "use-frame-synchronization");
6198 6200
6199 { 6201 {
6200 int i; 6202 int i;
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 6bb41110d5c..e089f9dea85 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -567,7 +567,7 @@ ftcrfont_draw (struct glyph_string *s,
567 unblock_input (); 567 unblock_input ();
568 return 0; 568 return 0;
569 } 569 }
570 BView_cr_dump_clipping (FRAME_HAIKU_VIEW (f), cr); 570 BView_cr_dump_clipping (FRAME_HAIKU_DRAWABLE (f), cr);
571#endif 571#endif
572 572
573 if (with_background) 573 if (with_background)
@@ -677,7 +677,11 @@ ftcrhbfont_begin_hb_font (struct font *font, double *position_unit)
677 677
678 ftcrfont_info->ft_size = ft_face->size; 678 ftcrfont_info->ft_size = ft_face->size;
679 hb_font_t *hb_font = fthbfont_begin_hb_font (font, position_unit); 679 hb_font_t *hb_font = fthbfont_begin_hb_font (font, position_unit);
680 if (ftcrfont_info->bitmap_position_unit) 680 /* HarfBuzz 5 correctly scales bitmap-only fonts without position
681 unit adjustment.
682 (https://github.com/harfbuzz/harfbuzz/issues/489) */
683 if (!hb_version_atleast (5, 0, 0)
684 && ftcrfont_info->bitmap_position_unit)
681 *position_unit = ftcrfont_info->bitmap_position_unit; 685 *position_unit = ftcrfont_info->bitmap_position_unit;
682 686
683 return hb_font; 687 return hb_font;
diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index b7590f68a48..983928442a1 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -1512,6 +1512,8 @@ public:
1512 1512
1513 BMessage *wait_for_release_message; 1513 BMessage *wait_for_release_message;
1514 int64 grabbed_buttons; 1514 int64 grabbed_buttons;
1515 BScreen screen;
1516 bool use_frame_synchronization;
1515 1517
1516 EmacsView () : BView (BRect (0, 0, 0, 0), "Emacs", 1518 EmacsView () : BView (BRect (0, 0, 0, 0), "Emacs",
1517 B_FOLLOW_NONE, B_WILL_DRAW), 1519 B_FOLLOW_NONE, B_WILL_DRAW),
@@ -1524,7 +1526,8 @@ public:
1524 cr_context (NULL), 1526 cr_context (NULL),
1525#endif 1527#endif
1526 wait_for_release_message (NULL), 1528 wait_for_release_message (NULL),
1527 grabbed_buttons (0) 1529 grabbed_buttons (0),
1530 use_frame_synchronization (false)
1528 { 1531 {
1529 1532
1530 } 1533 }
@@ -1547,6 +1550,16 @@ public:
1547 } 1550 }
1548 1551
1549 void 1552 void
1553 SetFrameSynchronization (bool sync)
1554 {
1555 if (LockLooper ())
1556 {
1557 use_frame_synchronization = sync;
1558 UnlockLooper ();
1559 }
1560 }
1561
1562 void
1550 MessageReceived (BMessage *msg) 1563 MessageReceived (BMessage *msg)
1551 { 1564 {
1552 uint32 buttons; 1565 uint32 buttons;
@@ -1722,14 +1735,14 @@ public:
1722 void 1735 void
1723 FlipBuffers (void) 1736 FlipBuffers (void)
1724 { 1737 {
1738 EmacsWindow *w;
1725 if (!LockLooper ()) 1739 if (!LockLooper ())
1726 gui_abort ("Failed to lock looper during buffer flip"); 1740 gui_abort ("Failed to lock looper during buffer flip");
1727 if (!offscreen_draw_view) 1741 if (!offscreen_draw_view)
1728 gui_abort ("Failed to lock offscreen view during buffer flip"); 1742 gui_abort ("Failed to lock offscreen view during buffer flip");
1729 1743
1730 offscreen_draw_view->Sync (); 1744 offscreen_draw_view->Sync ();
1731 1745 w = (EmacsWindow *) Window ();
1732 EmacsWindow *w = (EmacsWindow *) Window ();
1733 w->shown_flag = 0; 1746 w->shown_flag = 0;
1734 1747
1735 if (copy_bitmap && 1748 if (copy_bitmap &&
@@ -1750,6 +1763,11 @@ public:
1750 if (copy_bitmap->InitCheck () != B_OK) 1763 if (copy_bitmap->InitCheck () != B_OK)
1751 gui_abort ("Failed to init copy bitmap during buffer flip"); 1764 gui_abort ("Failed to init copy bitmap during buffer flip");
1752 1765
1766 /* Wait for VBLANK. If responding to the invalidation or buffer
1767 flipping takes longer than the blanking period, we lose. */
1768 if (use_frame_synchronization)
1769 screen.WaitForRetrace ();
1770
1753 Invalidate (&invalid_region); 1771 Invalidate (&invalid_region);
1754 invalid_region.MakeEmpty (); 1772 invalid_region.MakeEmpty ();
1755 UnlockLooper (); 1773 UnlockLooper ();
@@ -5474,3 +5492,12 @@ be_clear_grab_view (void)
5474 grab_view_locker.Unlock (); 5492 grab_view_locker.Unlock ();
5475 } 5493 }
5476} 5494}
5495
5496void
5497be_set_use_frame_synchronization (void *view, bool sync)
5498{
5499 EmacsView *vw;
5500
5501 vw = (EmacsView *) view;
5502 vw->SetFrameSynchronization (sync);
5503}
diff --git a/src/haiku_support.h b/src/haiku_support.h
index 76fe071f2c9..ca1808556a4 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -728,6 +728,7 @@ extern void be_lock_window (void *);
728extern void be_unlock_window (void *); 728extern void be_unlock_window (void *);
729extern bool be_get_explicit_workarea (int *, int *, int *, int *); 729extern bool be_get_explicit_workarea (int *, int *, int *, int *);
730extern void be_clear_grab_view (void); 730extern void be_clear_grab_view (void);
731extern void be_set_use_frame_synchronization (void *, bool);
731#ifdef __cplusplus 732#ifdef __cplusplus
732} 733}
733 734
diff --git a/src/haikufns.c b/src/haikufns.c
index f3667ac2f9d..aaa4e866228 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -949,6 +949,10 @@ haiku_create_frame (Lisp_Object parms)
949 || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))) 949 || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
950 kset_default_minibuffer_frame (kb, frame); 950 kset_default_minibuffer_frame (kb, frame);
951 951
952 /* Set whether or not frame synchronization is enabled. */
953 gui_default_parameter (f, parms, Quse_frame_synchronization, Qt,
954 NULL, NULL, RES_TYPE_BOOLEAN);
955
952 gui_default_parameter (f, parms, Qz_group, Qnil, 956 gui_default_parameter (f, parms, Qz_group, Qnil,
953 NULL, NULL, RES_TYPE_SYMBOL); 957 NULL, NULL, RES_TYPE_SYMBOL);
954 958
@@ -1501,9 +1505,9 @@ haiku_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval
1501 1505
1502 if (FRAME_HAIKU_VIEW (f)) 1506 if (FRAME_HAIKU_VIEW (f))
1503 { 1507 {
1504 BView_draw_lock (FRAME_HAIKU_VIEW (f), false, 0, 0, 0, 0); 1508 BView_draw_lock (FRAME_HAIKU_DRAWABLE (f), false, 0, 0, 0, 0);
1505 BView_SetViewColor (FRAME_HAIKU_VIEW (f), background); 1509 BView_SetViewColor (FRAME_HAIKU_DRAWABLE (f), background);
1506 BView_draw_unlock (FRAME_HAIKU_VIEW (f)); 1510 BView_draw_unlock (FRAME_HAIKU_DRAWABLE (f));
1507 1511
1508 FRAME_OUTPUT_DATA (f)->cursor_fg = background; 1512 FRAME_OUTPUT_DATA (f)->cursor_fg = background;
1509 update_face_from_frame_parameter (f, Qbackground_color, arg); 1513 update_face_from_frame_parameter (f, Qbackground_color, arg);
@@ -2115,6 +2119,13 @@ haiku_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
2115 update_face_from_frame_parameter (f, Qmouse_color, arg); 2119 update_face_from_frame_parameter (f, Qmouse_color, arg);
2116} 2120}
2117 2121
2122static void
2123haiku_set_use_frame_synchronization (struct frame *f, Lisp_Object arg,
2124 Lisp_Object oldval)
2125{
2126 be_set_use_frame_synchronization (FRAME_HAIKU_VIEW (f), !NILP (arg));
2127}
2128
2118 2129
2119 2130
2120DEFUN ("haiku-set-mouse-absolute-pixel-position", 2131DEFUN ("haiku-set-mouse-absolute-pixel-position",
@@ -3128,6 +3139,7 @@ frame_parm_handler haiku_frame_parm_handlers[] =
3128 haiku_set_override_redirect, 3139 haiku_set_override_redirect,
3129 gui_set_no_special_glyphs, 3140 gui_set_no_special_glyphs,
3130 gui_set_alpha_background, 3141 gui_set_alpha_background,
3142 haiku_set_use_frame_synchronization,
3131 }; 3143 };
3132 3144
3133void 3145void
diff --git a/src/haikuterm.c b/src/haikuterm.c
index f2bee1263d3..c2d4e34ba25 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -163,15 +163,15 @@ haiku_clip_to_string (struct glyph_string *s)
163 /* If n[FOO].width is 0, it means to not draw at all, so set the 163 /* If n[FOO].width is 0, it means to not draw at all, so set the
164 clipping to some impossible value. */ 164 clipping to some impossible value. */
165 if (r[0].width <= 0) 165 if (r[0].width <= 0)
166 BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), 166 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f),
167 FRAME_PIXEL_WIDTH (s->f), 167 FRAME_PIXEL_WIDTH (s->f),
168 FRAME_PIXEL_HEIGHT (s->f), 168 FRAME_PIXEL_HEIGHT (s->f),
169 10, 10); 169 10, 10);
170 else 170 else
171 { 171 {
172 BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), r[0].x, 172 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f), r[0].x,
173 r[0].y, r[0].width, r[0].height); 173 r[0].y, r[0].width, r[0].height);
174 BView_invalidate_region (FRAME_HAIKU_VIEW (s->f), r[0].x, 174 BView_invalidate_region (FRAME_HAIKU_DRAWABLE (s->f), r[0].x,
175 r[0].y, r[0].width, r[0].height); 175 r[0].y, r[0].width, r[0].height);
176 } 176 }
177 } 177 }
@@ -181,15 +181,15 @@ haiku_clip_to_string (struct glyph_string *s)
181 /* If n[FOO].width is 0, it means to not draw at all, so set the 181 /* If n[FOO].width is 0, it means to not draw at all, so set the
182 clipping to some impossible value. */ 182 clipping to some impossible value. */
183 if (r[1].width <= 0) 183 if (r[1].width <= 0)
184 BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), 184 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f),
185 FRAME_PIXEL_WIDTH (s->f), 185 FRAME_PIXEL_WIDTH (s->f),
186 FRAME_PIXEL_HEIGHT (s->f), 186 FRAME_PIXEL_HEIGHT (s->f),
187 10, 10); 187 10, 10);
188 else 188 else
189 { 189 {
190 BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), r[1].x, r[1].y, 190 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f), r[1].x, r[1].y,
191 r[1].width, r[1].height); 191 r[1].width, r[1].height);
192 BView_invalidate_region (FRAME_HAIKU_VIEW (s->f), r[1].x, 192 BView_invalidate_region (FRAME_HAIKU_DRAWABLE (s->f), r[1].x,
193 r[1].y, r[1].width, r[1].height); 193 r[1].y, r[1].width, r[1].height);
194 } 194 }
195 } 195 }
@@ -198,9 +198,9 @@ haiku_clip_to_string (struct glyph_string *s)
198static void 198static void
199haiku_clip_to_string_exactly (struct glyph_string *s, struct glyph_string *dst) 199haiku_clip_to_string_exactly (struct glyph_string *s, struct glyph_string *dst)
200{ 200{
201 BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), s->x, s->y, 201 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (s->f), s->x, s->y,
202 s->width, s->height); 202 s->width, s->height);
203 BView_invalidate_region (FRAME_HAIKU_VIEW (s->f), s->x, 203 BView_invalidate_region (FRAME_HAIKU_DRAWABLE (s->f), s->x,
204 s->y, s->width, s->height); 204 s->y, s->width, s->height);
205} 205}
206 206
@@ -246,7 +246,7 @@ static void
246haiku_clear_frame_area (struct frame *f, int x, int y, 246haiku_clear_frame_area (struct frame *f, int x, int y,
247 int width, int height) 247 int width, int height)
248{ 248{
249 void *vw = FRAME_HAIKU_VIEW (f); 249 void *vw = FRAME_HAIKU_DRAWABLE (f);
250 block_input (); 250 block_input ();
251 BView_draw_lock (vw, true, x, y, width, height); 251 BView_draw_lock (vw, true, x, y, width, height);
252 BView_StartClip (vw); 252 BView_StartClip (vw);
@@ -261,7 +261,7 @@ haiku_clear_frame_area (struct frame *f, int x, int y,
261static void 261static void
262haiku_clear_frame (struct frame *f) 262haiku_clear_frame (struct frame *f)
263{ 263{
264 void *view = FRAME_HAIKU_VIEW (f); 264 void *view = FRAME_HAIKU_DRAWABLE (f);
265 265
266 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); 266 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
267 267
@@ -596,7 +596,7 @@ haiku_draw_box_rect (struct glyph_string *s, int left_x, int top_y,
596 int right_x, int bottom_y, int hwidth, int vwidth, 596 int right_x, int bottom_y, int hwidth, int vwidth,
597 bool left_p, bool right_p, struct haiku_rect *clip_rect) 597 bool left_p, bool right_p, struct haiku_rect *clip_rect)
598{ 598{
599 void *view = FRAME_HAIKU_VIEW (s->f); 599 void *view = FRAME_HAIKU_DRAWABLE (s->f);
600 struct face *face = s->face; 600 struct face *face = s->face;
601 601
602 BView_SetHighColor (view, face->box_color); 602 BView_SetHighColor (view, face->box_color);
@@ -660,7 +660,7 @@ haiku_draw_relief_rect (struct glyph_string *s, int left_x, int top_y,
660 uint32_t color_white, color_black; 660 uint32_t color_white, color_black;
661 void *view; 661 void *view;
662 662
663 view = FRAME_HAIKU_VIEW (s->f); 663 view = FRAME_HAIKU_DRAWABLE (s->f);
664 haiku_calculate_relief_colors (s, &color_white, &color_black); 664 haiku_calculate_relief_colors (s, &color_white, &color_black);
665 665
666 BView_SetHighColor (view, raised_p ? color_white : color_black); 666 BView_SetHighColor (view, raised_p ? color_white : color_black);
@@ -769,7 +769,7 @@ haiku_draw_underwave (struct glyph_string *s, int width, int x)
769 dy = wave_height - 1; 769 dy = wave_height - 1;
770 y = s->ybase - wave_height + 3; 770 y = s->ybase - wave_height + 3;
771 xmax = x + width; 771 xmax = x + width;
772 view = FRAME_HAIKU_VIEW (s->f); 772 view = FRAME_HAIKU_DRAWABLE (s->f);
773 773
774 BView_StartClip (view); 774 BView_StartClip (view);
775 haiku_clip_to_string (s); 775 haiku_clip_to_string (s);
@@ -811,7 +811,7 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
811 if (s->hl == DRAW_CURSOR) 811 if (s->hl == DRAW_CURSOR)
812 haiku_merge_cursor_foreground (s, &cursor_color, NULL); 812 haiku_merge_cursor_foreground (s, &cursor_color, NULL);
813 813
814 void *view = FRAME_HAIKU_VIEW (s->f); 814 void *view = FRAME_HAIKU_DRAWABLE (s->f);
815 815
816 if (face->underline) 816 if (face->underline)
817 { 817 {
@@ -1013,7 +1013,7 @@ static void
1013haiku_draw_plain_background (struct glyph_string *s, struct face *face, 1013haiku_draw_plain_background (struct glyph_string *s, struct face *face,
1014 int x, int y, int width, int height) 1014 int x, int y, int width, int height)
1015{ 1015{
1016 void *view = FRAME_HAIKU_VIEW (s->f); 1016 void *view = FRAME_HAIKU_DRAWABLE (s->f);
1017 unsigned long cursor_color; 1017 unsigned long cursor_color;
1018 1018
1019 if (s->hl == DRAW_CURSOR) 1019 if (s->hl == DRAW_CURSOR)
@@ -1075,7 +1075,7 @@ haiku_draw_stipple_background (struct glyph_string *s, struct face *face,
1075 unsigned long foreground, background; 1075 unsigned long foreground, background;
1076 void *view; 1076 void *view;
1077 1077
1078 view = FRAME_HAIKU_VIEW (s->f); 1078 view = FRAME_HAIKU_DRAWABLE (s->f);
1079 rec = haiku_get_bitmap_rec (s->f, s->face->stipple); 1079 rec = haiku_get_bitmap_rec (s->f, s->face->stipple);
1080 1080
1081 if (explicit_colors_p) 1081 if (explicit_colors_p)
@@ -1173,7 +1173,7 @@ haiku_draw_glyph_string_foreground (struct glyph_string *s)
1173 else 1173 else
1174 x = s->x; 1174 x = s->x;
1175 1175
1176 void *view = FRAME_HAIKU_VIEW (s->f); 1176 void *view = FRAME_HAIKU_DRAWABLE (s->f);
1177 1177
1178 if (s->font_not_found_p) 1178 if (s->font_not_found_p)
1179 { 1179 {
@@ -1289,9 +1289,9 @@ haiku_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1289 else 1289 else
1290 color = s->face->foreground; 1290 color = s->face->foreground;
1291 1291
1292 BView_SetHighColor (FRAME_HAIKU_VIEW (s->f), color); 1292 BView_SetHighColor (FRAME_HAIKU_DRAWABLE (s->f), color);
1293 BView_SetPenSize (FRAME_HAIKU_VIEW (s->f), 1); 1293 BView_SetPenSize (FRAME_HAIKU_DRAWABLE (s->f), 1);
1294 BView_StrokeRectangle (FRAME_HAIKU_VIEW (s->f), 1294 BView_StrokeRectangle (FRAME_HAIKU_DRAWABLE (s->f),
1295 x, s->ybase - glyph->ascent, 1295 x, s->ybase - glyph->ascent,
1296 glyph->pixel_width, 1296 glyph->pixel_width,
1297 glyph->ascent + glyph->descent); 1297 glyph->ascent + glyph->descent);
@@ -1335,7 +1335,7 @@ haiku_draw_stretch_glyph_string (struct glyph_string *s)
1335 if (s->row->reversed_p) 1335 if (s->row->reversed_p)
1336 x -= width; 1336 x -= width;
1337 1337
1338 void *view = FRAME_HAIKU_VIEW (s->f); 1338 void *view = FRAME_HAIKU_DRAWABLE (s->f);
1339 unsigned long cursor_color; 1339 unsigned long cursor_color;
1340 1340
1341 haiku_merge_cursor_foreground (s, NULL, &cursor_color); 1341 haiku_merge_cursor_foreground (s, NULL, &cursor_color);
@@ -1401,14 +1401,14 @@ haiku_draw_stretch_glyph_string (struct glyph_string *s)
1401static void 1401static void
1402haiku_start_clip (struct glyph_string *s) 1402haiku_start_clip (struct glyph_string *s)
1403{ 1403{
1404 void *view = FRAME_HAIKU_VIEW (s->f); 1404 void *view = FRAME_HAIKU_DRAWABLE (s->f);
1405 BView_StartClip (view); 1405 BView_StartClip (view);
1406} 1406}
1407 1407
1408static void 1408static void
1409haiku_end_clip (struct glyph_string *s) 1409haiku_end_clip (struct glyph_string *s)
1410{ 1410{
1411 void *view = FRAME_HAIKU_VIEW (s->f); 1411 void *view = FRAME_HAIKU_DRAWABLE (s->f);
1412 BView_EndClip (view); 1412 BView_EndClip (view);
1413} 1413}
1414 1414
@@ -1428,7 +1428,7 @@ haiku_clip_to_row (struct window *w, struct glyph_row *row,
1428 width = window_width; 1428 width = window_width;
1429 height = row->visible_height; 1429 height = row->visible_height;
1430 1430
1431 BView_ClipToRect (FRAME_HAIKU_VIEW (f), x, y, width, height); 1431 BView_ClipToRect (FRAME_HAIKU_DRAWABLE (f), x, y, width, height);
1432} 1432}
1433 1433
1434static void 1434static void
@@ -1448,7 +1448,7 @@ haiku_draw_composite_glyph_string_foreground (struct glyph_string *s)
1448{ 1448{
1449 int i, j, x; 1449 int i, j, x;
1450 struct font *font = s->font; 1450 struct font *font = s->font;
1451 void *view = FRAME_HAIKU_VIEW (s->f); 1451 void *view = FRAME_HAIKU_DRAWABLE (s->f);
1452 struct face *face = s->face; 1452 struct face *face = s->face;
1453 1453
1454 /* If first glyph of S has a left box line, start drawing the text 1454 /* If first glyph of S has a left box line, start drawing the text
@@ -1670,7 +1670,7 @@ haiku_draw_image_glyph_string (struct glyph_string *s)
1670 if (s->slice.y == 0) 1670 if (s->slice.y == 0)
1671 y += box_line_vwidth; 1671 y += box_line_vwidth;
1672 1672
1673 view = FRAME_HAIKU_VIEW (s->f); 1673 view = FRAME_HAIKU_DRAWABLE (s->f);
1674 bitmap = s->img->pixmap; 1674 bitmap = s->img->pixmap;
1675 1675
1676 s->stippled_p = face->stipple != 0; 1676 s->stippled_p = face->stipple != 0;
@@ -1803,7 +1803,7 @@ haiku_draw_image_glyph_string (struct glyph_string *s)
1803static void 1803static void
1804haiku_draw_glyph_string (struct glyph_string *s) 1804haiku_draw_glyph_string (struct glyph_string *s)
1805{ 1805{
1806 void *view = FRAME_HAIKU_VIEW (s->f);; 1806 void *view = FRAME_HAIKU_DRAWABLE (s->f);;
1807 struct face *face = s->face; 1807 struct face *face = s->face;
1808 1808
1809 block_input (); 1809 block_input ();
@@ -2001,7 +2001,7 @@ haiku_after_update_window_line (struct window *w,
2001 block_input (); 2001 block_input ();
2002 if (face) 2002 if (face)
2003 { 2003 {
2004 void *view = FRAME_HAIKU_VIEW (f); 2004 void *view = FRAME_HAIKU_DRAWABLE (f);
2005 BView_draw_lock (view, false, 0, 0, 0, 0); 2005 BView_draw_lock (view, false, 0, 0, 0, 0);
2006 BView_StartClip (view); 2006 BView_StartClip (view);
2007 BView_SetHighColor (view, (face->background_defaulted_p 2007 BView_SetHighColor (view, (face->background_defaulted_p
@@ -2010,7 +2010,7 @@ haiku_after_update_window_line (struct window *w,
2010 BView_FillRectangle (view, 0, y, width, height); 2010 BView_FillRectangle (view, 0, y, width, height);
2011 BView_FillRectangle (view, FRAME_PIXEL_WIDTH (f) - width, 2011 BView_FillRectangle (view, FRAME_PIXEL_WIDTH (f) - width,
2012 y, width, height); 2012 y, width, height);
2013 BView_invalidate_region (FRAME_HAIKU_VIEW (f), 2013 BView_invalidate_region (FRAME_HAIKU_DRAWABLE (f),
2014 0, y, width, height); 2014 0, y, width, height);
2015 BView_invalidate_region (view, FRAME_PIXEL_WIDTH (f) - width, 2015 BView_invalidate_region (view, FRAME_PIXEL_WIDTH (f) - width,
2016 y, width, height); 2016 y, width, height);
@@ -2075,7 +2075,7 @@ haiku_draw_hollow_cursor (struct window *w, struct glyph_row *row)
2075 void *view; 2075 void *view;
2076 2076
2077 f = XFRAME (WINDOW_FRAME (w)); 2077 f = XFRAME (WINDOW_FRAME (w));
2078 view = FRAME_HAIKU_VIEW (f); 2078 view = FRAME_HAIKU_DRAWABLE (f);
2079 2079
2080 /* Get the glyph the cursor is on. If we can't tell because 2080 /* Get the glyph the cursor is on. If we can't tell because
2081 the current matrix is invalid or such, give up. */ 2081 the current matrix is invalid or such, give up. */
@@ -2148,7 +2148,7 @@ haiku_draw_bar_cursor (struct window *w, struct glyph_row *row,
2148 } 2148 }
2149 else 2149 else
2150 { 2150 {
2151 view = FRAME_HAIKU_VIEW (f); 2151 view = FRAME_HAIKU_DRAWABLE (f);
2152 face = FACE_FROM_ID (f, cursor_glyph->face_id); 2152 face = FACE_FROM_ID (f, cursor_glyph->face_id);
2153 2153
2154 /* If the glyph's background equals the color we normally draw 2154 /* If the glyph's background equals the color we normally draw
@@ -2334,7 +2334,7 @@ haiku_draw_vertical_window_border (struct window *w,
2334 struct face *face; 2334 struct face *face;
2335 2335
2336 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID); 2336 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
2337 void *view = FRAME_HAIKU_VIEW (f); 2337 void *view = FRAME_HAIKU_DRAWABLE (f);
2338 BView_draw_lock (view, true, x, y_0, 1, y_1); 2338 BView_draw_lock (view, true, x, y_0, 1, y_1);
2339 BView_StartClip (view); 2339 BView_StartClip (view);
2340 if (face) 2340 if (face)
@@ -2384,7 +2384,7 @@ haiku_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
2384 unsigned long color_last = (face_last 2384 unsigned long color_last = (face_last
2385 ? face_last->foreground 2385 ? face_last->foreground
2386 : FRAME_FOREGROUND_PIXEL (f)); 2386 : FRAME_FOREGROUND_PIXEL (f));
2387 void *view = FRAME_HAIKU_VIEW (f); 2387 void *view = FRAME_HAIKU_DRAWABLE (f);
2388 2388
2389 BView_draw_lock (view, true, x0, y0, x1 - x0 + 1, y1 - y0 + 1); 2389 BView_draw_lock (view, true, x0, y0, x1 - x0 + 1, y1 - y0 + 1);
2390 BView_StartClip (view); 2390 BView_StartClip (view);
@@ -2554,7 +2554,7 @@ haiku_scroll_bar_create (struct window *w, int left, int top,
2554 void *view; 2554 void *view;
2555 2555
2556 f = XFRAME (WINDOW_FRAME (w)); 2556 f = XFRAME (WINDOW_FRAME (w));
2557 view = FRAME_HAIKU_VIEW (f); 2557 view = FRAME_HAIKU_DRAWABLE (f);
2558 2558
2559 block_input (); 2559 block_input ();
2560 bar = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER); 2560 bar = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER);
@@ -2604,7 +2604,7 @@ haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int p
2604 width = window_width; 2604 width = window_width;
2605 top = WINDOW_SCROLL_BAR_AREA_Y (w); 2605 top = WINDOW_SCROLL_BAR_AREA_Y (w);
2606 height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w); 2606 height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
2607 view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w)); 2607 view = FRAME_HAIKU_DRAWABLE (WINDOW_XFRAME (w));
2608 2608
2609 block_input (); 2609 block_input ();
2610 2610
@@ -2663,7 +2663,7 @@ haiku_set_vertical_scroll_bar (struct window *w, int portion, int whole, int pos
2663 left = WINDOW_SCROLL_BAR_AREA_X (w); 2663 left = WINDOW_SCROLL_BAR_AREA_X (w);
2664 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w); 2664 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2665 2665
2666 view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w)); 2666 view = FRAME_HAIKU_DRAWABLE (WINDOW_XFRAME (w));
2667 2667
2668 block_input (); 2668 block_input ();
2669 if (NILP (w->vertical_scroll_bar)) 2669 if (NILP (w->vertical_scroll_bar))
@@ -2712,7 +2712,7 @@ haiku_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2712 uint32 col; 2712 uint32 col;
2713 2713
2714 f = XFRAME (WINDOW_FRAME (w)); 2714 f = XFRAME (WINDOW_FRAME (w));
2715 view = FRAME_HAIKU_VIEW (f); 2715 view = FRAME_HAIKU_DRAWABLE (f);
2716 face = p->face; 2716 face = p->face;
2717 2717
2718 block_input (); 2718 block_input ();
@@ -2828,7 +2828,7 @@ static void
2828haiku_scroll_run (struct window *w, struct run *run) 2828haiku_scroll_run (struct window *w, struct run *run)
2829{ 2829{
2830 struct frame *f = XFRAME (w->frame); 2830 struct frame *f = XFRAME (w->frame);
2831 void *view = FRAME_HAIKU_VIEW (f); 2831 void *view = FRAME_HAIKU_DRAWABLE (f);
2832 int x, y, width, height, from_y, to_y, bottom_y; 2832 int x, y, width, height, from_y, to_y, bottom_y;
2833 window_box (w, ANY_AREA, &x, &y, &width, &height); 2833 window_box (w, ANY_AREA, &x, &y, &width, &height);
2834 2834
@@ -3211,9 +3211,9 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
3211 continue; 3211 continue;
3212 } 3212 }
3213 3213
3214 BView_draw_lock (FRAME_HAIKU_VIEW (f), false, 0, 0, 0, 0); 3214 BView_draw_lock (FRAME_HAIKU_DRAWABLE (f), false, 0, 0, 0, 0);
3215 BView_resize_to (FRAME_HAIKU_VIEW (f), width, height); 3215 BView_resize_to (FRAME_HAIKU_DRAWABLE (f), width, height);
3216 BView_draw_unlock (FRAME_HAIKU_VIEW (f)); 3216 BView_draw_unlock (FRAME_HAIKU_DRAWABLE (f));
3217 3217
3218 if (width != FRAME_PIXEL_WIDTH (f) 3218 if (width != FRAME_PIXEL_WIDTH (f)
3219 || height != FRAME_PIXEL_HEIGHT (f) 3219 || height != FRAME_PIXEL_HEIGHT (f)
@@ -4126,7 +4126,7 @@ haiku_flash (struct frame *f)
4126 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f); 4126 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4127 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f); 4127 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4128 int width = flash_right - flash_left; 4128 int width = flash_right - flash_left;
4129 void *view = FRAME_HAIKU_VIEW (f); 4129 void *view = FRAME_HAIKU_DRAWABLE (f);
4130 object_wait_info info; 4130 object_wait_info info;
4131 bigtime_t wakeup; 4131 bigtime_t wakeup;
4132 4132
@@ -4454,7 +4454,7 @@ haiku_clear_under_internal_border (struct frame *f)
4454 ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID) 4454 ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
4455 : INTERNAL_BORDER_FACE_ID)); 4455 : INTERNAL_BORDER_FACE_ID));
4456 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); 4456 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
4457 void *view = FRAME_HAIKU_VIEW (f); 4457 void *view = FRAME_HAIKU_DRAWABLE (f);
4458 4458
4459 block_input (); 4459 block_input ();
4460 BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f), 4460 BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
@@ -4496,7 +4496,7 @@ haiku_scroll_bar_remove (struct scroll_bar *bar)
4496 struct frame *f; 4496 struct frame *f;
4497 4497
4498 f = WINDOW_XFRAME (XWINDOW (bar->window)); 4498 f = WINDOW_XFRAME (XWINDOW (bar->window));
4499 view = FRAME_HAIKU_VIEW (f); 4499 view = FRAME_HAIKU_DRAWABLE (f);
4500 4500
4501 block_input (); 4501 block_input ();
4502 BView_forget_scroll_bar (view, bar->left, bar->top, 4502 BView_forget_scroll_bar (view, bar->left, bar->top,
diff --git a/src/haikuterm.h b/src/haikuterm.h
index 02a364f6712..b603c0a482f 100644
--- a/src/haikuterm.h
+++ b/src/haikuterm.h
@@ -275,7 +275,8 @@ struct scroll_bar
275#define MAKE_FRAME_DIRTY(f) (FRAME_DIRTY_P (f) = 1) 275#define MAKE_FRAME_DIRTY(f) (FRAME_DIRTY_P (f) = 1)
276#define FRAME_OUTPUT_DATA(f) ((f)->output_data.haiku) 276#define FRAME_OUTPUT_DATA(f) ((f)->output_data.haiku)
277#define FRAME_HAIKU_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window) 277#define FRAME_HAIKU_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window)
278#define FRAME_HAIKU_VIEW(f) ((MAKE_FRAME_DIRTY (f)), FRAME_OUTPUT_DATA (f)->view) 278#define FRAME_HAIKU_VIEW(f) (FRAME_OUTPUT_DATA (f)->view)
279#define FRAME_HAIKU_DRAWABLE(f) ((MAKE_FRAME_DIRTY (f)), FRAME_HAIKU_VIEW (f))
279#define FRAME_HAIKU_MENU_BAR(f) (FRAME_OUTPUT_DATA (f)->menubar) 280#define FRAME_HAIKU_MENU_BAR(f) (FRAME_OUTPUT_DATA (f)->menubar)
280#define FRAME_DISPLAY_INFO(f) (FRAME_OUTPUT_DATA (f)->display_info) 281#define FRAME_DISPLAY_INFO(f) (FRAME_OUTPUT_DATA (f)->display_info)
281#define FRAME_FONT(f) (FRAME_OUTPUT_DATA (f)->font) 282#define FRAME_FONT(f) (FRAME_OUTPUT_DATA (f)->font)
@@ -287,7 +288,7 @@ struct scroll_bar
287#ifdef USE_BE_CAIRO 288#ifdef USE_BE_CAIRO
288#define FRAME_CR_CONTEXT(f) \ 289#define FRAME_CR_CONTEXT(f) \
289 (FRAME_HAIKU_VIEW (f) \ 290 (FRAME_HAIKU_VIEW (f) \
290 ? EmacsView_cairo_context (FRAME_HAIKU_VIEW (f)) \ 291 ? EmacsView_cairo_context (FRAME_HAIKU_DRAWABLE (f)) \
291 : NULL) 292 : NULL)
292#endif 293#endif
293 294
diff --git a/src/indent.c b/src/indent.c
index fd2e7636656..d2dfaee254e 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -2345,7 +2345,15 @@ whether or not it is currently displayed in some window. */)
2345 last line that it occupies. */ 2345 last line that it occupies. */
2346 if (it_start < ZV) 2346 if (it_start < ZV)
2347 { 2347 {
2348 while (IT_CHARPOS (it) <= it_start) 2348 if ((it.bidi_it.scan_dir > 0)
2349 ? IT_CHARPOS (it) < it_start
2350 : IT_CHARPOS (it) > it_start)
2351 {
2352 it.vpos = 0;
2353 it.current_y = 0;
2354 move_it_by_lines (&it, 1);
2355 }
2356 while (IT_CHARPOS (it) == it_start)
2349 { 2357 {
2350 it.vpos = 0; 2358 it.vpos = 0;
2351 it.current_y = 0; 2359 it.current_y = 0;
diff --git a/src/keyboard.c b/src/keyboard.c
index 2863058d633..719226caedc 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1295,7 +1295,8 @@ command_loop_1 (void)
1295 /* Note that the value cell will never directly contain nil 1295 /* Note that the value cell will never directly contain nil
1296 if the symbol is a local variable. */ 1296 if the symbol is a local variable. */
1297 if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks)) 1297 if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
1298 safe_run_hooks (Qpost_command_hook); 1298 safe_run_hooks_maybe_narrowed (Qpost_command_hook,
1299 XWINDOW (selected_window));
1299 1300
1300 /* If displaying a message, resize the echo area window to fit 1301 /* If displaying a message, resize the echo area window to fit
1301 that message's size exactly. */ 1302 that message's size exactly. */
@@ -1330,6 +1331,7 @@ command_loop_1 (void)
1330 display_malloc_warning (); 1331 display_malloc_warning ();
1331 1332
1332 Vdeactivate_mark = Qnil; 1333 Vdeactivate_mark = Qnil;
1334 backtrace_yet = false;
1333 1335
1334 /* Don't ignore mouse movements for more than a single command 1336 /* Don't ignore mouse movements for more than a single command
1335 loop. (This flag is set in xdisp.c whenever the tool bar is 1337 loop. (This flag is set in xdisp.c whenever the tool bar is
@@ -1461,7 +1463,9 @@ command_loop_1 (void)
1461 } 1463 }
1462 Vthis_command = cmd; 1464 Vthis_command = cmd;
1463 Vreal_this_command = cmd; 1465 Vreal_this_command = cmd;
1464 safe_run_hooks (Qpre_command_hook); 1466
1467 safe_run_hooks_maybe_narrowed (Qpre_command_hook,
1468 XWINDOW (selected_window));
1465 1469
1466 already_adjusted = 0; 1470 already_adjusted = 0;
1467 1471
@@ -1513,7 +1517,8 @@ command_loop_1 (void)
1513 } 1517 }
1514 kset_last_prefix_arg (current_kboard, Vcurrent_prefix_arg); 1518 kset_last_prefix_arg (current_kboard, Vcurrent_prefix_arg);
1515 1519
1516 safe_run_hooks (Qpost_command_hook); 1520 safe_run_hooks_maybe_narrowed (Qpost_command_hook,
1521 XWINDOW (selected_window));
1517 1522
1518 /* If displaying a message, resize the echo area window to fit 1523 /* If displaying a message, resize the echo area window to fit
1519 that message's size exactly. Do this only if the echo area 1524 that message's size exactly. Do this only if the echo area
@@ -1837,7 +1842,7 @@ safe_run_hooks_1 (ptrdiff_t nargs, Lisp_Object *args)
1837static Lisp_Object 1842static Lisp_Object
1838safe_run_hooks_error (Lisp_Object error, ptrdiff_t nargs, Lisp_Object *args) 1843safe_run_hooks_error (Lisp_Object error, ptrdiff_t nargs, Lisp_Object *args)
1839{ 1844{
1840 eassert (nargs == 2); 1845 eassert (nargs >= 2 && nargs <= 4);
1841 AUTO_STRING (format, "Error in %s (%S): %S"); 1846 AUTO_STRING (format, "Error in %s (%S): %S");
1842 Lisp_Object hook = args[0]; 1847 Lisp_Object hook = args[0];
1843 Lisp_Object fun = args[1]; 1848 Lisp_Object fun = args[1];
@@ -1895,6 +1900,33 @@ safe_run_hooks (Lisp_Object hook)
1895 unbind_to (count, Qnil); 1900 unbind_to (count, Qnil);
1896} 1901}
1897 1902
1903void
1904safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct window *w)
1905{
1906 specpdl_ref count = SPECPDL_INDEX ();
1907
1908 specbind (Qinhibit_quit, Qt);
1909
1910 if (current_buffer->long_line_optimizations_p)
1911 narrow_to_region_internal (make_fixnum (get_narrowed_begv (w, PT)),
1912 make_fixnum (get_narrowed_zv (w, PT)),
1913 true);
1914
1915 run_hook_with_args (2, ((Lisp_Object []) {hook, hook}), safe_run_hook_funcall);
1916 unbind_to (count, Qnil);
1917}
1918
1919void
1920safe_run_hooks_2 (Lisp_Object hook, Lisp_Object arg1, Lisp_Object arg2)
1921{
1922 specpdl_ref count = SPECPDL_INDEX ();
1923
1924 specbind (Qinhibit_quit, Qt);
1925 run_hook_with_args (4, ((Lisp_Object []) {hook, hook, arg1, arg2}),
1926 safe_run_hook_funcall);
1927 unbind_to (count, Qnil);
1928}
1929
1898 1930
1899/* Nonzero means polling for input is temporarily suppressed. */ 1931/* Nonzero means polling for input is temporarily suppressed. */
1900 1932
@@ -4622,6 +4654,11 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
4622 /* If timer is ripe, run it if it hasn't been run. */ 4654 /* If timer is ripe, run it if it hasn't been run. */
4623 if (ripe) 4655 if (ripe)
4624 { 4656 {
4657 /* If we got here, presumably `decode_timer` has checked
4658 that this timer has not yet been triggered. */
4659 eassert (NILP (AREF (chosen_timer, 0)));
4660 /* In a production build, where assertions compile to
4661 nothing, we still want to play it safe here. */
4625 if (NILP (AREF (chosen_timer, 0))) 4662 if (NILP (AREF (chosen_timer, 0)))
4626 { 4663 {
4627 specpdl_ref count = SPECPDL_INDEX (); 4664 specpdl_ref count = SPECPDL_INDEX ();
@@ -4640,8 +4677,8 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
4640 4677
4641 /* Since we have handled the event, 4678 /* Since we have handled the event,
4642 we don't need to tell the caller to wake up and do it. */ 4679 we don't need to tell the caller to wake up and do it. */
4643 /* But the caller must still wait for the next timer, so 4680 /* But the caller must still wait for the next timer, so
4644 return 0 to indicate that. */ 4681 return 0 to indicate that. */
4645 } 4682 }
4646 4683
4647 nexttime = make_timespec (0, 0); 4684 nexttime = make_timespec (0, 0);
@@ -12622,23 +12659,39 @@ Buffer modification stores t in this variable. */);
12622 12659
12623 DEFVAR_LISP ("pre-command-hook", Vpre_command_hook, 12660 DEFVAR_LISP ("pre-command-hook", Vpre_command_hook,
12624 doc: /* Normal hook run before each command is executed. 12661 doc: /* Normal hook run before each command is executed.
12625If an unhandled error happens in running this hook, 12662
12626the function in which the error occurred is unconditionally removed, since 12663If an unhandled error happens in running this hook, the function in
12627otherwise the error might happen repeatedly and make Emacs nonfunctional. 12664which the error occurred is unconditionally removed, since otherwise
12665the error might happen repeatedly and make Emacs nonfunctional.
12666
12667Note that, when the current buffer contains one or more lines whose
12668length is above `long-line-threshold', these hook functions are called
12669with the buffer narrowed to a small portion around point, and the
12670narrowing is locked (see `narrow-to-region'), so that these hook
12671functions cannot use `widen' to gain access to other portions of
12672buffer text.
12628 12673
12629See also `post-command-hook'. */); 12674See also `post-command-hook'. */);
12630 Vpre_command_hook = Qnil; 12675 Vpre_command_hook = Qnil;
12631 12676
12632 DEFVAR_LISP ("post-command-hook", Vpost_command_hook, 12677 DEFVAR_LISP ("post-command-hook", Vpost_command_hook,
12633 doc: /* Normal hook run after each command is executed. 12678 doc: /* Normal hook run after each command is executed.
12634If an unhandled error happens in running this hook, 12679
12635the function in which the error occurred is unconditionally removed, since 12680If an unhandled error happens in running this hook, the function in
12636otherwise the error might happen repeatedly and make Emacs nonfunctional. 12681which the error occurred is unconditionally removed, since otherwise
12682the error might happen repeatedly and make Emacs nonfunctional.
12637 12683
12638It is a bad idea to use this hook for expensive processing. If 12684It is a bad idea to use this hook for expensive processing. If
12639unavoidable, wrap your code in `(while-no-input (redisplay) CODE)' to 12685unavoidable, wrap your code in `(while-no-input (redisplay) CODE)' to
12640avoid making Emacs unresponsive while the user types. 12686avoid making Emacs unresponsive while the user types.
12641 12687
12688Note that, when the current buffer contains one or more lines whose
12689length is above `long-line-threshold', these hook functions are called
12690with the buffer narrowed to a small portion around point, and the
12691narrowing is locked (see `narrow-to-region'), so that these hook
12692functions cannot use `widen' to gain access to other portions of
12693buffer text.
12694
12642See also `pre-command-hook'. */); 12695See also `pre-command-hook'. */);
12643 Vpost_command_hook = Qnil; 12696 Vpost_command_hook = Qnil;
12644 12697
@@ -12914,7 +12967,10 @@ This variable only has an effect when Transient Mark mode is enabled.
12914 12967
12915If the value is `only', only temporarily active regions (usually made 12968If the value is `only', only temporarily active regions (usually made
12916by mouse-dragging or shift-selection) set the window system's primary 12969by mouse-dragging or shift-selection) set the window system's primary
12917selection. */); 12970selection.
12971
12972If this variable causes the region to be set as the primary selection,
12973`post-select-region-hook' is then run afterwards. */);
12918 Vselect_active_regions = Qt; 12974 Vselect_active_regions = Qt;
12919 12975
12920 DEFVAR_LISP ("saved-region-selection", 12976 DEFVAR_LISP ("saved-region-selection",
diff --git a/src/lisp.h b/src/lisp.h
index 8fcc9b6e75a..2f73ba4c617 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3793,10 +3793,10 @@ make_symbol_constant (Lisp_Object sym)
3793 3793
3794/* Buffer-local variable access functions. */ 3794/* Buffer-local variable access functions. */
3795 3795
3796INLINE int 3796INLINE bool
3797blv_found (struct Lisp_Buffer_Local_Value *blv) 3797blv_found (struct Lisp_Buffer_Local_Value *blv)
3798{ 3798{
3799 eassert (blv->found == !EQ (blv->defcell, blv->valcell)); 3799 eassert (blv->found == !BASE_EQ (blv->defcell, blv->valcell));
3800 return blv->found; 3800 return blv->found;
3801} 3801}
3802 3802
@@ -4530,6 +4530,7 @@ extern Lisp_Object Vrun_hooks;
4530extern Lisp_Object Vsignaling_function; 4530extern Lisp_Object Vsignaling_function;
4531extern Lisp_Object inhibit_lisp_code; 4531extern Lisp_Object inhibit_lisp_code;
4532extern bool signal_quit_p (Lisp_Object); 4532extern bool signal_quit_p (Lisp_Object);
4533extern bool backtrace_yet;
4533 4534
4534/* To run a normal hook, use the appropriate function from the list below. 4535/* To run a normal hook, use the appropriate function from the list below.
4535 The calling convention: 4536 The calling convention:
@@ -4679,6 +4680,7 @@ extern void save_restriction_restore (Lisp_Object);
4679extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool); 4680extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool);
4680extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, 4681extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
4681 ptrdiff_t, bool); 4682 ptrdiff_t, bool);
4683extern Lisp_Object narrow_to_region_internal (Lisp_Object, Lisp_Object, bool);
4682extern void init_editfns (void); 4684extern void init_editfns (void);
4683extern void syms_of_editfns (void); 4685extern void syms_of_editfns (void);
4684 4686
@@ -4829,6 +4831,8 @@ extern bool detect_input_pending (void);
4829extern bool detect_input_pending_ignore_squeezables (void); 4831extern bool detect_input_pending_ignore_squeezables (void);
4830extern bool detect_input_pending_run_timers (bool); 4832extern bool detect_input_pending_run_timers (bool);
4831extern void safe_run_hooks (Lisp_Object); 4833extern void safe_run_hooks (Lisp_Object);
4834extern void safe_run_hooks_maybe_narrowed (Lisp_Object, struct window *);
4835extern void safe_run_hooks_2 (Lisp_Object, Lisp_Object, Lisp_Object);
4832extern void cmd_error_internal (Lisp_Object, const char *); 4836extern void cmd_error_internal (Lisp_Object, const char *);
4833extern Lisp_Object command_loop_2 (Lisp_Object); 4837extern Lisp_Object command_loop_2 (Lisp_Object);
4834extern Lisp_Object read_menu_command (void); 4838extern Lisp_Object read_menu_command (void);
@@ -4941,7 +4945,8 @@ extern void setup_process_coding_systems (Lisp_Object);
4941#endif 4945#endif
4942 4946
4943extern int emacs_spawn (pid_t *, int, int, int, char **, char **, 4947extern int emacs_spawn (pid_t *, int, int, int, char **, char **,
4944 const char *, const char *, const sigset_t *); 4948 const char *, const char *, bool, bool,
4949 const sigset_t *);
4945extern char **make_environment_block (Lisp_Object) ATTRIBUTE_RETURNS_NONNULL; 4950extern char **make_environment_block (Lisp_Object) ATTRIBUTE_RETURNS_NONNULL;
4946extern void init_callproc_1 (void); 4951extern void init_callproc_1 (void);
4947extern void init_callproc (void); 4952extern void init_callproc (void);
diff --git a/src/lread.c b/src/lread.c
index 0720774db2b..ccccd79cd7c 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -131,25 +131,15 @@ static ptrdiff_t read_from_string_limit;
131/* Position in object from which characters are being read by `readchar'. */ 131/* Position in object from which characters are being read by `readchar'. */
132static EMACS_INT readchar_offset; 132static EMACS_INT readchar_offset;
133 133
134/* This contains the last string skipped with #@. */ 134struct saved_string {
135static char *saved_doc_string; 135 char *string; /* string in allocated buffer */
136/* Length of buffer allocated in saved_doc_string. */ 136 ptrdiff_t size; /* allocated size of buffer */
137static ptrdiff_t saved_doc_string_size; 137 ptrdiff_t length; /* length of string in buffer */
138/* Length of actual data in saved_doc_string. */ 138 file_offset position; /* position in file the string came from */
139static ptrdiff_t saved_doc_string_length; 139};
140/* This is the file position that string came from. */ 140
141static file_offset saved_doc_string_position; 141/* The last two strings skipped with #@ (most recent first). */
142 142static struct saved_string saved_strings[2];
143/* This contains the previous string skipped with #@.
144 We copy it from saved_doc_string when a new string
145 is put in saved_doc_string. */
146static char *prev_saved_doc_string;
147/* Length of buffer allocated in prev_saved_doc_string. */
148static ptrdiff_t prev_saved_doc_string_size;
149/* Length of actual data in prev_saved_doc_string. */
150static ptrdiff_t prev_saved_doc_string_length;
151/* This is the file position that string came from. */
152static file_offset prev_saved_doc_string_position;
153 143
154/* A list of file names for files being loaded in Fload. Used to 144/* A list of file names for files being loaded in Fload. Used to
155 check for recursive loads. */ 145 check for recursive loads. */
@@ -1605,13 +1595,12 @@ Return t if the file exists and loads successfully. */)
1605 if (!NILP (Ffboundp (Qdo_after_load_evaluation))) 1595 if (!NILP (Ffboundp (Qdo_after_load_evaluation)))
1606 call1 (Qdo_after_load_evaluation, hist_file_name) ; 1596 call1 (Qdo_after_load_evaluation, hist_file_name) ;
1607 1597
1608 xfree (saved_doc_string); 1598 for (int i = 0; i < ARRAYELTS (saved_strings); i++)
1609 saved_doc_string = 0; 1599 {
1610 saved_doc_string_size = 0; 1600 xfree (saved_strings[i].string);
1611 1601 saved_strings[i].string = NULL;
1612 xfree (prev_saved_doc_string); 1602 saved_strings[i].size = 0;
1613 prev_saved_doc_string = 0; 1603 }
1614 prev_saved_doc_string_size = 0;
1615 1604
1616 if (!noninteractive && (NILP (nomessage) || force_load_messages)) 1605 if (!noninteractive && (NILP (nomessage) || force_load_messages))
1617 { 1606 {
@@ -2261,7 +2250,7 @@ readevalloop (Lisp_Object readcharfun,
2261 /* Set point and ZV around stuff to be read. */ 2250 /* Set point and ZV around stuff to be read. */
2262 Fgoto_char (start); 2251 Fgoto_char (start);
2263 if (!NILP (end)) 2252 if (!NILP (end))
2264 Fnarrow_to_region (make_fixnum (BEGV), end, Qnil); 2253 Fnarrow_to_region (make_fixnum (BEGV), end);
2265 2254
2266 /* Just for cleanliness, convert END to a marker 2255 /* Just for cleanliness, convert END to a marker
2267 if it is an integer. */ 2256 if it is an integer. */
@@ -3056,7 +3045,6 @@ read_string_literal (char stackbuf[VLA_ELEMS (stackbufsize)],
3056 /* True if we saw an escape sequence specifying 3045 /* True if we saw an escape sequence specifying
3057 a single-byte character. */ 3046 a single-byte character. */
3058 bool force_singlebyte = false; 3047 bool force_singlebyte = false;
3059 bool cancel = false;
3060 ptrdiff_t nchars = 0; 3048 ptrdiff_t nchars = 0;
3061 3049
3062 int ch; 3050 int ch;
@@ -3085,8 +3073,6 @@ read_string_literal (char stackbuf[VLA_ELEMS (stackbufsize)],
3085 case ' ': 3073 case ' ':
3086 case '\n': 3074 case '\n':
3087 /* `\SPC' and `\LF' generate no characters at all. */ 3075 /* `\SPC' and `\LF' generate no characters at all. */
3088 if (p == read_buffer)
3089 cancel = true;
3090 continue; 3076 continue;
3091 default: 3077 default:
3092 UNREAD (ch); 3078 UNREAD (ch);
@@ -3152,15 +3138,6 @@ read_string_literal (char stackbuf[VLA_ELEMS (stackbufsize)],
3152 if (ch < 0) 3138 if (ch < 0)
3153 end_of_file_error (); 3139 end_of_file_error ();
3154 3140
3155 /* If purifying, and string starts with \ newline,
3156 return zero instead. This is for doc strings
3157 that we are really going to find in etc/DOC.nn.nn. */
3158 if (!NILP (Vpurify_flag) && NILP (Vdoc_file_name) && cancel)
3159 {
3160 unbind_to (count, Qnil);
3161 return make_fixnum (0);
3162 }
3163
3164 if (!force_multibyte && force_singlebyte) 3141 if (!force_multibyte && force_singlebyte)
3165 { 3142 {
3166 /* READ_BUFFER contains raw 8-bit bytes and no multibyte 3143 /* READ_BUFFER contains raw 8-bit bytes and no multibyte
@@ -3457,57 +3434,95 @@ skip_lazy_string (Lisp_Object readcharfun)
3457 record the last string that we skipped, 3434 record the last string that we skipped,
3458 and record where in the file it comes from. */ 3435 and record where in the file it comes from. */
3459 3436
3460 /* But first exchange saved_doc_string 3437 /* First exchange the two saved_strings. */
3461 with prev_saved_doc_string, so we save two strings. */ 3438 verify (ARRAYELTS (saved_strings) == 2);
3462 { 3439 struct saved_string t = saved_strings[0];
3463 char *temp = saved_doc_string; 3440 saved_strings[0] = saved_strings[1];
3464 ptrdiff_t temp_size = saved_doc_string_size; 3441 saved_strings[1] = t;
3465 file_offset temp_pos = saved_doc_string_position;
3466 ptrdiff_t temp_len = saved_doc_string_length;
3467
3468 saved_doc_string = prev_saved_doc_string;
3469 saved_doc_string_size = prev_saved_doc_string_size;
3470 saved_doc_string_position = prev_saved_doc_string_position;
3471 saved_doc_string_length = prev_saved_doc_string_length;
3472
3473 prev_saved_doc_string = temp;
3474 prev_saved_doc_string_size = temp_size;
3475 prev_saved_doc_string_position = temp_pos;
3476 prev_saved_doc_string_length = temp_len;
3477 }
3478 3442
3479 enum { extra = 100 }; 3443 enum { extra = 100 };
3480 if (saved_doc_string_size == 0) 3444 struct saved_string *ss = &saved_strings[0];
3445 if (ss->size == 0)
3481 { 3446 {
3482 saved_doc_string = xmalloc (nskip + extra); 3447 ss->size = nskip + extra;
3483 saved_doc_string_size = nskip + extra; 3448 ss->string = xmalloc (ss->size);
3484 } 3449 }
3485 if (nskip > saved_doc_string_size) 3450 else if (nskip > ss->size)
3486 { 3451 {
3487 saved_doc_string = xrealloc (saved_doc_string, nskip + extra); 3452 ss->size = nskip + extra;
3488 saved_doc_string_size = nskip + extra; 3453 ss->string = xrealloc (ss->string, ss->size);
3489 } 3454 }
3490 3455
3491 FILE *instream = infile->stream; 3456 FILE *instream = infile->stream;
3492 saved_doc_string_position = (file_tell (instream) - infile->lookahead); 3457 ss->position = (file_tell (instream) - infile->lookahead);
3493 3458
3494 /* Copy that many bytes into saved_doc_string. */ 3459 /* Copy that many bytes into the saved string. */
3495 ptrdiff_t i = 0; 3460 ptrdiff_t i = 0;
3496 int c = 0; 3461 int c = 0;
3497 for (int n = min (nskip, infile->lookahead); n > 0; n--) 3462 for (int n = min (nskip, infile->lookahead); n > 0; n--)
3498 saved_doc_string[i++] = c = infile->buf[--infile->lookahead]; 3463 ss->string[i++] = c = infile->buf[--infile->lookahead];
3499 block_input (); 3464 block_input ();
3500 for (; i < nskip && c >= 0; i++) 3465 for (; i < nskip && c >= 0; i++)
3501 saved_doc_string[i] = c = getc (instream); 3466 ss->string[i] = c = getc (instream);
3502 unblock_input (); 3467 unblock_input ();
3503 3468
3504 saved_doc_string_length = i; 3469 ss->length = i;
3505 } 3470 }
3506 else 3471 else
3507 /* Skip that many bytes. */ 3472 /* Skip that many bytes. */
3508 skip_dyn_bytes (readcharfun, nskip); 3473 skip_dyn_bytes (readcharfun, nskip);
3509} 3474}
3510 3475
3476/* Given a lazy-loaded string designator VAL, return the actual string.
3477 VAL is (FILENAME . POS). */
3478static Lisp_Object
3479get_lazy_string (Lisp_Object val)
3480{
3481 /* Get a doc string from the file we are loading.
3482 If it's in a saved string, get it from there.
3483
3484 Here, we don't know if the string is a bytecode string or a doc
3485 string. As a bytecode string must be unibyte, we always return a
3486 unibyte string. If it is actually a doc string, caller must make
3487 it multibyte. */
3488
3489 /* We used to emit negative positions for 'user variables' (whose doc
3490 strings started with an asterisk); take the absolute value for
3491 compatibility. */
3492 EMACS_INT pos = eabs (XFIXNUM (XCDR (val)));
3493 struct saved_string *ss = &saved_strings[0];
3494 struct saved_string *ssend = ss + ARRAYELTS (saved_strings);
3495 while (ss < ssend
3496 && !(pos >= ss->position && pos < ss->position + ss->length))
3497 ss++;
3498 if (ss >= ssend)
3499 return get_doc_string (val, 1, 0);
3500
3501 ptrdiff_t start = pos - ss->position;
3502 char *str = ss->string;
3503 ptrdiff_t from = start;
3504 ptrdiff_t to = start;
3505
3506 /* Process quoting with ^A, and find the end of the string,
3507 which is marked with ^_ (037). */
3508 while (str[from] != 037)
3509 {
3510 int c = str[from++];
3511 if (c == 1)
3512 {
3513 c = str[from++];
3514 str[to++] = (c == 1 ? c
3515 : c == '0' ? 0
3516 : c == '_' ? 037
3517 : c);
3518 }
3519 else
3520 str[to++] = c;
3521 }
3522
3523 return make_unibyte_string (str + start, to - start);
3524}
3525
3511 3526
3512/* Length of prefix only consisting of symbol constituent characters. */ 3527/* Length of prefix only consisting of symbol constituent characters. */
3513static ptrdiff_t 3528static ptrdiff_t
@@ -4249,6 +4264,15 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4249 XSETCDR (e->u.list.tail, obj); 4264 XSETCDR (e->u.list.tail, obj);
4250 read_stack_pop (); 4265 read_stack_pop ();
4251 obj = e->u.list.head; 4266 obj = e->u.list.head;
4267
4268 /* Hack: immediately convert (#$ . FIXNUM) to the corresponding
4269 string if load-force-doc-strings is set. */
4270 if (load_force_doc_strings
4271 && BASE_EQ (XCAR (obj), Vload_file_name)
4272 && !NILP (XCAR (obj))
4273 && FIXNUMP (XCDR (obj)))
4274 obj = get_lazy_string (obj);
4275
4252 break; 4276 break;
4253 } 4277 }
4254 4278
diff --git a/src/marker.c b/src/marker.c
index 3c8e628762e..9727586f424 100644
--- a/src/marker.c
+++ b/src/marker.c
@@ -214,11 +214,12 @@ buf_charpos_to_bytepos (struct buffer *b, ptrdiff_t charpos)
214 We have one known above and one known below. 214 We have one known above and one known below.
215 Scan, counting characters, from whichever one is closer. */ 215 Scan, counting characters, from whichever one is closer. */
216 216
217 eassert (best_below <= charpos && charpos <= best_above);
217 if (charpos - best_below < best_above - charpos) 218 if (charpos - best_below < best_above - charpos)
218 { 219 {
219 bool record = charpos - best_below > 5000; 220 bool record = charpos - best_below > 5000;
220 221
221 while (best_below != charpos) 222 while (best_below < charpos)
222 { 223 {
223 best_below++; 224 best_below++;
224 best_below_byte += buf_next_char_len (b, best_below_byte); 225 best_below_byte += buf_next_char_len (b, best_below_byte);
@@ -243,7 +244,7 @@ buf_charpos_to_bytepos (struct buffer *b, ptrdiff_t charpos)
243 { 244 {
244 bool record = best_above - charpos > 5000; 245 bool record = best_above - charpos > 5000;
245 246
246 while (best_above != charpos) 247 while (best_above > charpos)
247 { 248 {
248 best_above--; 249 best_above--;
249 best_above_byte -= buf_prev_char_len (b, best_above_byte); 250 best_above_byte -= buf_prev_char_len (b, best_above_byte);
diff --git a/src/nsfns.m b/src/nsfns.m
index 433df059610..1d3dcd31243 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -1057,6 +1057,7 @@ frame_parm_handler ns_frame_parm_handlers[] =
1057 0, /* x_set_override_redirect */ 1057 0, /* x_set_override_redirect */
1058 gui_set_no_special_glyphs, 1058 gui_set_no_special_glyphs,
1059 gui_set_alpha_background, 1059 gui_set_alpha_background,
1060 NULL,
1060#ifdef NS_IMPL_COCOA 1061#ifdef NS_IMPL_COCOA
1061 ns_set_appearance, 1062 ns_set_appearance,
1062 ns_set_transparent_titlebar, 1063 ns_set_transparent_titlebar,
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index d998c3d938c..beaf28f69d9 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -991,6 +991,7 @@ frame_parm_handler pgtk_frame_parm_handlers[] =
991 pgtk_set_override_redirect, 991 pgtk_set_override_redirect,
992 gui_set_no_special_glyphs, 992 gui_set_no_special_glyphs,
993 pgtk_set_alpha_background, 993 pgtk_set_alpha_background,
994 NULL,
994 }; 995 };
995 996
996 997
diff --git a/src/print.c b/src/print.c
index 7303e847aa2..1c96ec14b86 100644
--- a/src/print.c
+++ b/src/print.c
@@ -63,16 +63,17 @@ static Lisp_Object being_printed[PRINT_CIRCLE];
63/* Last char printed to stdout by printchar. */ 63/* Last char printed to stdout by printchar. */
64static unsigned int printchar_stdout_last; 64static unsigned int printchar_stdout_last;
65 65
66struct print_buffer
67{
68 char *buffer; /* Allocated buffer. */
69 ptrdiff_t size; /* Size of allocated buffer. */
70 ptrdiff_t pos; /* Chars stored in buffer. */
71 ptrdiff_t pos_byte; /* Bytes stored in buffer. */
72};
73
66/* When printing into a buffer, first we put the text in this 74/* When printing into a buffer, first we put the text in this
67 block, then insert it all at once. */ 75 block, then insert it all at once. */
68static char *print_buffer; 76static struct print_buffer print_buffer;
69
70/* Size allocated in print_buffer. */
71static ptrdiff_t print_buffer_size;
72/* Chars stored in print_buffer. */
73static ptrdiff_t print_buffer_pos;
74/* Bytes stored in print_buffer. */
75static ptrdiff_t print_buffer_pos_byte;
76 77
77/* Vprint_number_table is a table, that keeps objects that are going to 78/* Vprint_number_table is a table, that keeps objects that are going to
78 be printed, to allow use of #n= and #n# to express sharing. 79 be printed, to allow use of #n= and #n# to express sharing.
@@ -91,121 +92,139 @@ bool print_output_debug_flag EXTERNALLY_VISIBLE = 1;
91 92
92/* Low level output routines for characters and strings. */ 93/* Low level output routines for characters and strings. */
93 94
94/* Lisp functions to do output using a stream
95 must have the stream in a variable called printcharfun
96 and must start with PRINTPREPARE, end with PRINTFINISH.
97 Use printchar to output one character,
98 or call strout to output a block of characters. */
99
100#define PRINTPREPARE \
101 ptrdiff_t old_point = -1, start_point = -1; \
102 ptrdiff_t old_point_byte = -1, start_point_byte = -1; \
103 specpdl_ref specpdl_count = SPECPDL_INDEX (); \
104 bool multibyte \
105 = !NILP (BVAR (current_buffer, enable_multibyte_characters)); \
106 Lisp_Object original = printcharfun; \
107 record_unwind_current_buffer (); \
108 specbind(Qprint__unreadable_callback_buffer, Fcurrent_buffer ()); \
109 if (NILP (printcharfun)) printcharfun = Qt; \
110 if (BUFFERP (printcharfun)) \
111 { \
112 if (XBUFFER (printcharfun) != current_buffer) \
113 Fset_buffer (printcharfun); \
114 printcharfun = Qnil; \
115 } \
116 if (MARKERP (printcharfun)) \
117 { \
118 ptrdiff_t marker_pos; \
119 if (! XMARKER (printcharfun)->buffer) \
120 error ("Marker does not point anywhere"); \
121 if (XMARKER (printcharfun)->buffer != current_buffer) \
122 set_buffer_internal (XMARKER (printcharfun)->buffer); \
123 marker_pos = marker_position (printcharfun); \
124 if (marker_pos < BEGV || marker_pos > ZV) \
125 signal_error ("Marker is outside the accessible " \
126 "part of the buffer", printcharfun); \
127 old_point = PT; \
128 old_point_byte = PT_BYTE; \
129 SET_PT_BOTH (marker_pos, \
130 marker_byte_position (printcharfun)); \
131 start_point = PT; \
132 start_point_byte = PT_BYTE; \
133 printcharfun = Qnil; \
134 } \
135 if (NILP (printcharfun)) \
136 { \
137 Lisp_Object string; \
138 if (NILP (BVAR (current_buffer, enable_multibyte_characters)) \
139 && ! print_escape_multibyte) \
140 specbind (Qprint_escape_multibyte, Qt); \
141 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)) \
142 && ! print_escape_nonascii) \
143 specbind (Qprint_escape_nonascii, Qt); \
144 if (print_buffer != 0) \
145 { \
146 string = make_string_from_bytes (print_buffer, \
147 print_buffer_pos, \
148 print_buffer_pos_byte); \
149 record_unwind_protect (print_unwind, string); \
150 } \
151 else \
152 { \
153 int new_size = 1000; \
154 print_buffer = xmalloc (new_size); \
155 print_buffer_size = new_size; \
156 record_unwind_protect_void (print_free_buffer); \
157 } \
158 print_buffer_pos = 0; \
159 print_buffer_pos_byte = 0; \
160 } \
161 if (EQ (printcharfun, Qt) && ! noninteractive) \
162 setup_echo_area_for_printing (multibyte);
163
164#define PRINTFINISH \
165 if (NILP (printcharfun)) \
166 { \
167 if (print_buffer_pos != print_buffer_pos_byte \
168 && NILP (BVAR (current_buffer, enable_multibyte_characters)))\
169 { \
170 USE_SAFE_ALLOCA; \
171 unsigned char *temp = SAFE_ALLOCA (print_buffer_pos + 1); \
172 copy_text ((unsigned char *) print_buffer, temp, \
173 print_buffer_pos_byte, 1, 0); \
174 insert_1_both ((char *) temp, print_buffer_pos, \
175 print_buffer_pos, 0, 1, 0); \
176 SAFE_FREE (); \
177 } \
178 else \
179 insert_1_both (print_buffer, print_buffer_pos, \
180 print_buffer_pos_byte, 0, 1, 0); \
181 signal_after_change (PT - print_buffer_pos, 0, print_buffer_pos);\
182 } \
183 if (MARKERP (original)) \
184 set_marker_both (original, Qnil, PT, PT_BYTE); \
185 if (old_point >= 0) \
186 SET_PT_BOTH (old_point + (old_point >= start_point \
187 ? PT - start_point : 0), \
188 old_point_byte + (old_point_byte >= start_point_byte \
189 ? PT_BYTE - start_point_byte : 0)); \
190 unbind_to (specpdl_count, Qnil); \
191
192/* This is used to free the print buffer; we don't simply record xfree 95/* This is used to free the print buffer; we don't simply record xfree
193 since print_buffer can be reallocated during the printing. */ 96 since print_buffer can be reallocated during the printing. */
194
195static void 97static void
196print_free_buffer (void) 98print_free_buffer (void)
197{ 99{
198 xfree (print_buffer); 100 xfree (print_buffer.buffer);
199 print_buffer = NULL; 101 print_buffer.buffer = NULL;
200} 102}
201 103
202/* This is used to restore the saved contents of print_buffer 104/* This is used to restore the saved contents of print_buffer
203 when there is a recursive call to print. */ 105 when there is a recursive call to print. */
204
205static void 106static void
206print_unwind (Lisp_Object saved_text) 107print_unwind (Lisp_Object saved_text)
207{ 108{
208 memcpy (print_buffer, SDATA (saved_text), SCHARS (saved_text)); 109 memcpy (print_buffer.buffer, SDATA (saved_text), SCHARS (saved_text));
110}
111
112/* Lisp functions to do output using a stream must start with a call to
113 print_prepare, and end with calling print_finish.
114 Use printchar to output one character, or call strout to output a
115 block of characters. */
116
117/* State carried between print_prepare and print_finish. */
118struct print_context
119{
120 Lisp_Object printcharfun;
121 Lisp_Object old_printcharfun;
122 ptrdiff_t old_point, start_point;
123 ptrdiff_t old_point_byte, start_point_byte;
124 specpdl_ref specpdl_count;
125};
126
127static inline struct print_context
128print_prepare (Lisp_Object printcharfun)
129{
130 struct print_context pc = {
131 .old_printcharfun = printcharfun,
132 .old_point = -1,
133 .start_point = -1,
134 .old_point_byte = -1,
135 .start_point_byte = -1,
136 .specpdl_count = SPECPDL_INDEX (),
137 };
138 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
139 record_unwind_current_buffer ();
140 specbind(Qprint__unreadable_callback_buffer, Fcurrent_buffer ());
141 if (NILP (printcharfun))
142 printcharfun = Qt;
143 if (BUFFERP (printcharfun))
144 {
145 if (XBUFFER (printcharfun) != current_buffer)
146 Fset_buffer (printcharfun);
147 printcharfun = Qnil;
148 }
149 if (MARKERP (printcharfun))
150 {
151 if (! XMARKER (printcharfun)->buffer)
152 error ("Marker does not point anywhere");
153 if (XMARKER (printcharfun)->buffer != current_buffer)
154 set_buffer_internal (XMARKER (printcharfun)->buffer);
155 ptrdiff_t marker_pos = marker_position (printcharfun);
156 if (marker_pos < BEGV || marker_pos > ZV)
157 signal_error ("Marker is outside the accessible part of the buffer",
158 printcharfun);
159 pc.old_point = PT;
160 pc.old_point_byte = PT_BYTE;
161 SET_PT_BOTH (marker_pos, marker_byte_position (printcharfun));
162 pc.start_point = PT;
163 pc.start_point_byte = PT_BYTE;
164 printcharfun = Qnil;
165 }
166 if (NILP (printcharfun))
167 {
168 if (NILP (BVAR (current_buffer, enable_multibyte_characters))
169 && ! print_escape_multibyte)
170 specbind (Qprint_escape_multibyte, Qt);
171 if (! NILP (BVAR (current_buffer, enable_multibyte_characters))
172 && ! print_escape_nonascii)
173 specbind (Qprint_escape_nonascii, Qt);
174 if (print_buffer.buffer != NULL)
175 {
176 Lisp_Object string = make_string_from_bytes (print_buffer.buffer,
177 print_buffer.pos,
178 print_buffer.pos_byte);
179 record_unwind_protect (print_unwind, string);
180 }
181 else
182 {
183 int new_size = 1000;
184 print_buffer.buffer = xmalloc (new_size);
185 print_buffer.size = new_size;
186 record_unwind_protect_void (print_free_buffer);
187 }
188 print_buffer.pos = 0;
189 print_buffer.pos_byte = 0;
190 }
191 if (EQ (printcharfun, Qt) && ! noninteractive)
192 setup_echo_area_for_printing (multibyte);
193 pc.printcharfun = printcharfun;
194 return pc;
195}
196
197static inline void
198print_finish (struct print_context *pc)
199{
200 if (NILP (pc->printcharfun))
201 {
202 if (print_buffer.pos != print_buffer.pos_byte
203 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
204 {
205 USE_SAFE_ALLOCA;
206 unsigned char *temp = SAFE_ALLOCA (print_buffer.pos + 1);
207 copy_text ((unsigned char *) print_buffer.buffer, temp,
208 print_buffer.pos_byte, 1, 0);
209 insert_1_both ((char *) temp, print_buffer.pos,
210 print_buffer.pos, 0, 1, 0);
211 SAFE_FREE ();
212 }
213 else
214 insert_1_both (print_buffer.buffer, print_buffer.pos,
215 print_buffer.pos_byte, 0, 1, 0);
216 signal_after_change (PT - print_buffer.pos, 0, print_buffer.pos);
217 }
218 if (MARKERP (pc->old_printcharfun))
219 set_marker_both (pc->old_printcharfun, Qnil, PT, PT_BYTE);
220 if (pc->old_point >= 0)
221 SET_PT_BOTH (pc->old_point
222 + (pc->old_point >= pc->start_point
223 ? PT - pc->start_point : 0),
224 pc->old_point_byte
225 + (pc->old_point_byte >= pc->start_point_byte
226 ? PT_BYTE - pc->start_point_byte : 0));
227 unbind_to (pc->specpdl_count, Qnil);
209} 228}
210 229
211/* Print character CH to the stdio stream STREAM. */ 230/* Print character CH to the stdio stream STREAM. */
@@ -293,13 +312,14 @@ printchar (unsigned int ch, Lisp_Object fun)
293 312
294 if (NILP (fun)) 313 if (NILP (fun))
295 { 314 {
296 ptrdiff_t incr = len - (print_buffer_size - print_buffer_pos_byte); 315 ptrdiff_t incr = len - (print_buffer.size - print_buffer.pos_byte);
297 if (incr > 0) 316 if (incr > 0)
298 print_buffer = xpalloc (print_buffer, &print_buffer_size, 317 print_buffer.buffer = xpalloc (print_buffer.buffer,
299 incr, -1, 1); 318 &print_buffer.size,
300 memcpy (print_buffer + print_buffer_pos_byte, str, len); 319 incr, -1, 1);
301 print_buffer_pos += 1; 320 memcpy (print_buffer.buffer + print_buffer.pos_byte, str, len);
302 print_buffer_pos_byte += len; 321 print_buffer.pos += 1;
322 print_buffer.pos_byte += len;
303 } 323 }
304 else if (noninteractive) 324 else if (noninteractive)
305 { 325 {
@@ -358,12 +378,13 @@ strout (const char *ptr, ptrdiff_t size, ptrdiff_t size_byte,
358{ 378{
359 if (NILP (printcharfun)) 379 if (NILP (printcharfun))
360 { 380 {
361 ptrdiff_t incr = size_byte - (print_buffer_size - print_buffer_pos_byte); 381 ptrdiff_t incr = size_byte - (print_buffer.size - print_buffer.pos_byte);
362 if (incr > 0) 382 if (incr > 0)
363 print_buffer = xpalloc (print_buffer, &print_buffer_size, incr, -1, 1); 383 print_buffer.buffer = xpalloc (print_buffer.buffer,
364 memcpy (print_buffer + print_buffer_pos_byte, ptr, size_byte); 384 &print_buffer.size, incr, -1, 1);
365 print_buffer_pos += size; 385 memcpy (print_buffer.buffer + print_buffer.pos_byte, ptr, size_byte);
366 print_buffer_pos_byte += size_byte; 386 print_buffer.pos += size;
387 print_buffer.pos_byte += size_byte;
367 } 388 }
368 else if (noninteractive && EQ (printcharfun, Qt)) 389 else if (noninteractive && EQ (printcharfun, Qt))
369 { 390 {
@@ -527,14 +548,14 @@ PRINTCHARFUN defaults to the value of `standard-output' (which see). */)
527 if (NILP (printcharfun)) 548 if (NILP (printcharfun))
528 printcharfun = Vstandard_output; 549 printcharfun = Vstandard_output;
529 CHECK_FIXNUM (character); 550 CHECK_FIXNUM (character);
530 PRINTPREPARE; 551 struct print_context pc = print_prepare (printcharfun);
531 printchar (XFIXNUM (character), printcharfun); 552 printchar (XFIXNUM (character), pc.printcharfun);
532 PRINTFINISH; 553 print_finish (&pc);
533 return character; 554 return character;
534} 555}
535 556
536/* Print the contents of a unibyte C string STRING using PRINTCHARFUN. 557/* Print the contents of a unibyte C string STRING using PRINTCHARFUN.
537 The caller should arrange to put this inside PRINTPREPARE and PRINTFINISH. 558 The caller should arrange to put this inside print_prepare and print_finish.
538 Do not use this on the contents of a Lisp string. */ 559 Do not use this on the contents of a Lisp string. */
539 560
540static void 561static void
@@ -550,9 +571,9 @@ print_c_string (char const *string, Lisp_Object printcharfun)
550static void 571static void
551write_string (const char *data, Lisp_Object printcharfun) 572write_string (const char *data, Lisp_Object printcharfun)
552{ 573{
553 PRINTPREPARE; 574 struct print_context pc = print_prepare (printcharfun);
554 print_c_string (data, printcharfun); 575 print_c_string (data, pc.printcharfun);
555 PRINTFINISH; 576 print_finish (&pc);
556} 577}
557 578
558 579
@@ -605,21 +626,21 @@ If PRINTCHARFUN is omitted or nil, the value of `standard-output' is used. */)
605 626
606 if (NILP (printcharfun)) 627 if (NILP (printcharfun))
607 printcharfun = Vstandard_output; 628 printcharfun = Vstandard_output;
608 PRINTPREPARE; 629 struct print_context pc = print_prepare (printcharfun);
609 630
610 if (NILP (ensure)) 631 if (NILP (ensure))
611 val = Qt; 632 val = Qt;
612 /* Difficult to check if at line beginning so abort. */ 633 /* Difficult to check if at line beginning so abort. */
613 else if (FUNCTIONP (printcharfun)) 634 else if (FUNCTIONP (pc.printcharfun))
614 signal_error ("Unsupported function argument", printcharfun); 635 signal_error ("Unsupported function argument", pc.printcharfun);
615 else if (noninteractive && !NILP (printcharfun)) 636 else if (noninteractive && !NILP (pc.printcharfun))
616 val = printchar_stdout_last == 10 ? Qnil : Qt; 637 val = printchar_stdout_last == 10 ? Qnil : Qt;
617 else 638 else
618 val = NILP (Fbolp ()) ? Qt : Qnil; 639 val = NILP (Fbolp ()) ? Qt : Qnil;
619 640
620 if (!NILP (val)) 641 if (!NILP (val))
621 printchar ('\n', printcharfun); 642 printchar ('\n', pc.printcharfun);
622 PRINTFINISH; 643 print_finish (&pc);
623 return val; 644 return val;
624} 645}
625 646
@@ -750,9 +771,9 @@ means "use default values for all the print-related settings". */)
750 if (!NILP (overrides)) 771 if (!NILP (overrides))
751 print_bind_overrides (overrides); 772 print_bind_overrides (overrides);
752 773
753 PRINTPREPARE; 774 struct print_context pc = print_prepare (printcharfun);
754 print (object, printcharfun, 1); 775 print (object, pc.printcharfun, 1);
755 PRINTFINISH; 776 print_finish (&pc);
756 777
757 return unbind_to (count, object); 778 return unbind_to (count, object);
758} 779}
@@ -787,11 +808,10 @@ A printed representation of an object is text which describes that object. */)
787 No need for specbind, since errors deactivate the mark. */ 808 No need for specbind, since errors deactivate the mark. */
788 Lisp_Object save_deactivate_mark = Vdeactivate_mark; 809 Lisp_Object save_deactivate_mark = Vdeactivate_mark;
789 810
790 Lisp_Object printcharfun = Vprin1_to_string_buffer; 811 struct print_context pc = print_prepare (Vprin1_to_string_buffer);
791 PRINTPREPARE; 812 print (object, pc.printcharfun, NILP (noescape));
792 print (object, printcharfun, NILP (noescape)); 813 /* Make Vprin1_to_string_buffer be the default buffer after print_finish */
793 /* Make Vprin1_to_string_buffer be the default buffer after PRINTFINISH */ 814 print_finish (&pc);
794 PRINTFINISH;
795 815
796 struct buffer *previous = current_buffer; 816 struct buffer *previous = current_buffer;
797 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer)); 817 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
@@ -836,15 +856,15 @@ is used instead. */)
836{ 856{
837 if (NILP (printcharfun)) 857 if (NILP (printcharfun))
838 printcharfun = Vstandard_output; 858 printcharfun = Vstandard_output;
839 PRINTPREPARE; 859 struct print_context pc = print_prepare (printcharfun);
840 if (STRINGP (object) 860 if (STRINGP (object)
841 && !string_intervals (object) 861 && !string_intervals (object)
842 && NILP (Vprint_continuous_numbering)) 862 && NILP (Vprint_continuous_numbering))
843 /* fast path for plain strings */ 863 /* fast path for plain strings */
844 print_string (object, printcharfun); 864 print_string (object, pc.printcharfun);
845 else 865 else
846 print (object, printcharfun, 0); 866 print (object, pc.printcharfun, 0);
847 PRINTFINISH; 867 print_finish (&pc);
848 return object; 868 return object;
849} 869}
850 870
@@ -875,11 +895,11 @@ is used instead. */)
875{ 895{
876 if (NILP (printcharfun)) 896 if (NILP (printcharfun))
877 printcharfun = Vstandard_output; 897 printcharfun = Vstandard_output;
878 PRINTPREPARE; 898 struct print_context pc = print_prepare (printcharfun);
879 printchar ('\n', printcharfun); 899 printchar ('\n', pc.printcharfun);
880 print (object, printcharfun, 1); 900 print (object, pc.printcharfun, 1);
881 printchar ('\n', printcharfun); 901 printchar ('\n', pc.printcharfun);
882 PRINTFINISH; 902 print_finish (&pc);
883 return object; 903 return object;
884} 904}
885 905
diff --git a/src/process.c b/src/process.c
index a15efa39bd1..23479c06194 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1243,14 +1243,31 @@ or t (process is stopped). */)
1243 return XPROCESS (process)->command; 1243 return XPROCESS (process)->command;
1244} 1244}
1245 1245
1246DEFUN ("process-tty-name", Fprocess_tty_name, Sprocess_tty_name, 1, 1, 0, 1246DEFUN ("process-tty-name", Fprocess_tty_name, Sprocess_tty_name, 1, 2, 0,
1247 doc: /* Return the name of the terminal PROCESS uses, or nil if none. 1247 doc: /* Return the name of the terminal PROCESS uses, or nil if none.
1248This is the terminal that the process itself reads and writes on, 1248This is the terminal that the process itself reads and writes on,
1249not the name of the pty that Emacs uses to talk with that terminal. */) 1249not the name of the pty that Emacs uses to talk with that terminal.
1250 (register Lisp_Object process) 1250
1251If STREAM is nil, return the terminal name if any of PROCESS's
1252standard streams use a terminal for communication. If STREAM is one
1253of `stdin', `stdout', or `stderr', return the name of the terminal
1254PROCESS uses for that stream specifically, or nil if that stream
1255communicates via a pipe. */)
1256 (register Lisp_Object process, Lisp_Object stream)
1251{ 1257{
1252 CHECK_PROCESS (process); 1258 CHECK_PROCESS (process);
1253 return XPROCESS (process)->tty_name; 1259 register struct Lisp_Process *p = XPROCESS (process);
1260
1261 if (NILP (stream))
1262 return p->tty_name;
1263 else if (EQ (stream, Qstdin))
1264 return p->pty_in ? p->tty_name : Qnil;
1265 else if (EQ (stream, Qstdout))
1266 return p->pty_out ? p->tty_name : Qnil;
1267 else if (EQ (stream, Qstderr))
1268 return p->pty_out && NILP (p->stderrproc) ? p->tty_name : Qnil;
1269 else
1270 signal_error ("Unknown stream", stream);
1254} 1271}
1255 1272
1256static void 1273static void
@@ -1316,6 +1333,19 @@ set_process_filter_masks (struct Lisp_Process *p)
1316 add_process_read_fd (p->infd); 1333 add_process_read_fd (p->infd);
1317} 1334}
1318 1335
1336static bool
1337is_pty_from_symbol (Lisp_Object symbol)
1338{
1339 if (EQ (symbol, Qpty))
1340 return true;
1341 else if (EQ (symbol, Qpipe))
1342 return false;
1343 else if (NILP (symbol))
1344 return !NILP (Vprocess_connection_type);
1345 else
1346 report_file_error ("Unknown connection type", symbol);
1347}
1348
1319DEFUN ("set-process-filter", Fset_process_filter, Sset_process_filter, 1349DEFUN ("set-process-filter", Fset_process_filter, Sset_process_filter,
1320 2, 2, 0, 1350 2, 2, 0,
1321 doc: /* Give PROCESS the filter function FILTER; nil means default. 1351 doc: /* Give PROCESS the filter function FILTER; nil means default.
@@ -1741,15 +1771,18 @@ signals to stop and continue a process.
1741:connection-type TYPE -- TYPE is control type of device used to 1771:connection-type TYPE -- TYPE is control type of device used to
1742communicate with subprocesses. Values are `pipe' to use a pipe, `pty' 1772communicate with subprocesses. Values are `pipe' to use a pipe, `pty'
1743to use a pty, or nil to use the default specified through 1773to use a pty, or nil to use the default specified through
1744`process-connection-type'. 1774`process-connection-type'. If TYPE is a cons (INPUT . OUTPUT), then
1775INPUT will be used for standard input and OUTPUT for standard output
1776(and standard error if `:stderr' is nil).
1745 1777
1746:filter FILTER -- Install FILTER as the process filter. 1778:filter FILTER -- Install FILTER as the process filter.
1747 1779
1748:sentinel SENTINEL -- Install SENTINEL as the process sentinel. 1780:sentinel SENTINEL -- Install SENTINEL as the process sentinel.
1749 1781
1750:stderr STDERR -- STDERR is either a buffer or a pipe process attached 1782:stderr STDERR -- STDERR is either a buffer or a pipe process attached
1751to the standard error of subprocess. Specifying this implies 1783to the standard error of subprocess. When specifying this, the
1752`:connection-type' is set to `pipe'. If STDERR is nil, standard error 1784subprocess's standard error will always communicate via a pipe, no
1785matter the value of `:connection-type'. If STDERR is nil, standard error
1753is mixed with standard output and sent to BUFFER or FILTER. (Note 1786is mixed with standard output and sent to BUFFER or FILTER. (Note
1754that specifying :stderr will create a new, separate (but associated) 1787that specifying :stderr will create a new, separate (but associated)
1755process, with its own filter and sentinel. See 1788process, with its own filter and sentinel. See
@@ -1845,22 +1878,20 @@ usage: (make-process &rest ARGS) */)
1845 CHECK_TYPE (NILP (tem), Qnull, tem); 1878 CHECK_TYPE (NILP (tem), Qnull, tem);
1846 1879
1847 tem = plist_get (contact, QCconnection_type); 1880 tem = plist_get (contact, QCconnection_type);
1848 if (EQ (tem, Qpty)) 1881 if (CONSP (tem))
1849 XPROCESS (proc)->pty_flag = true; 1882 {
1850 else if (EQ (tem, Qpipe)) 1883 XPROCESS (proc)->pty_in = is_pty_from_symbol (XCAR (tem));
1851 XPROCESS (proc)->pty_flag = false; 1884 XPROCESS (proc)->pty_out = is_pty_from_symbol (XCDR (tem));
1852 else if (NILP (tem)) 1885 }
1853 XPROCESS (proc)->pty_flag = !NILP (Vprocess_connection_type);
1854 else 1886 else
1855 report_file_error ("Unknown connection type", tem);
1856
1857 if (!NILP (stderrproc))
1858 { 1887 {
1859 pset_stderrproc (XPROCESS (proc), stderrproc); 1888 XPROCESS (proc)->pty_in = XPROCESS (proc)->pty_out =
1860 1889 is_pty_from_symbol (tem);
1861 XPROCESS (proc)->pty_flag = false;
1862 } 1890 }
1863 1891
1892 if (!NILP (stderrproc))
1893 pset_stderrproc (XPROCESS (proc), stderrproc);
1894
1864#ifdef HAVE_GNUTLS 1895#ifdef HAVE_GNUTLS
1865 /* AKA GNUTLS_INITSTAGE(proc). */ 1896 /* AKA GNUTLS_INITSTAGE(proc). */
1866 verify (GNUTLS_STAGE_EMPTY == 0); 1897 verify (GNUTLS_STAGE_EMPTY == 0);
@@ -2099,66 +2130,80 @@ static void
2099create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) 2130create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2100{ 2131{
2101 struct Lisp_Process *p = XPROCESS (process); 2132 struct Lisp_Process *p = XPROCESS (process);
2102 int inchannel, outchannel; 2133 int inchannel = -1, outchannel = -1;
2103 pid_t pid = -1; 2134 pid_t pid = -1;
2104 int vfork_errno; 2135 int vfork_errno;
2105 int forkin, forkout, forkerr = -1; 2136 int forkin, forkout, forkerr = -1;
2106 bool pty_flag = 0; 2137 bool pty_in = false, pty_out = false;
2107 char pty_name[PTY_NAME_SIZE]; 2138 char pty_name[PTY_NAME_SIZE];
2108 Lisp_Object lisp_pty_name = Qnil; 2139 Lisp_Object lisp_pty_name = Qnil;
2140 int ptychannel = -1, pty_tty = -1;
2109 sigset_t oldset; 2141 sigset_t oldset;
2110 2142
2111 /* Ensure that the SIGCHLD handler can notify 2143 /* Ensure that the SIGCHLD handler can notify
2112 `wait_reading_process_output'. */ 2144 `wait_reading_process_output'. */
2113 child_signal_init (); 2145 child_signal_init ();
2114 2146
2115 inchannel = outchannel = -1; 2147 if (p->pty_in || p->pty_out)
2116 2148 ptychannel = allocate_pty (pty_name);
2117 if (p->pty_flag)
2118 outchannel = inchannel = allocate_pty (pty_name);
2119 2149
2120 if (inchannel >= 0) 2150 if (ptychannel >= 0)
2121 { 2151 {
2122 p->open_fd[READ_FROM_SUBPROCESS] = inchannel;
2123#if ! defined (USG) || defined (USG_SUBTTY_WORKS) 2152#if ! defined (USG) || defined (USG_SUBTTY_WORKS)
2124 /* On most USG systems it does not work to open the pty's tty here, 2153 /* On most USG systems it does not work to open the pty's tty here,
2125 then close it and reopen it in the child. */ 2154 then close it and reopen it in the child. */
2126 /* Don't let this terminal become our controlling terminal 2155 /* Don't let this terminal become our controlling terminal
2127 (in case we don't have one). */ 2156 (in case we don't have one). */
2128 forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); 2157 pty_tty = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
2129 if (forkin < 0) 2158 if (pty_tty < 0)
2130 report_file_error ("Opening pty", Qnil); 2159 report_file_error ("Opening pty", Qnil);
2131 p->open_fd[SUBPROCESS_STDIN] = forkin;
2132#else
2133 forkin = forkout = -1;
2134#endif /* not USG, or USG_SUBTTY_WORKS */ 2160#endif /* not USG, or USG_SUBTTY_WORKS */
2135 pty_flag = 1; 2161 pty_in = p->pty_in;
2162 pty_out = p->pty_out;
2136 lisp_pty_name = build_string (pty_name); 2163 lisp_pty_name = build_string (pty_name);
2137 } 2164 }
2165
2166 /* Set up stdin for the child process. */
2167 if (ptychannel >= 0 && p->pty_in)
2168 {
2169 p->open_fd[SUBPROCESS_STDIN] = forkin = pty_tty;
2170 outchannel = ptychannel;
2171 }
2138 else 2172 else
2139 { 2173 {
2140 if (emacs_pipe (p->open_fd + SUBPROCESS_STDIN) != 0 2174 if (emacs_pipe (p->open_fd + SUBPROCESS_STDIN) != 0)
2141 || emacs_pipe (p->open_fd + READ_FROM_SUBPROCESS) != 0)
2142 report_file_error ("Creating pipe", Qnil); 2175 report_file_error ("Creating pipe", Qnil);
2143 forkin = p->open_fd[SUBPROCESS_STDIN]; 2176 forkin = p->open_fd[SUBPROCESS_STDIN];
2144 outchannel = p->open_fd[WRITE_TO_SUBPROCESS]; 2177 outchannel = p->open_fd[WRITE_TO_SUBPROCESS];
2178 }
2179
2180 /* Set up stdout for the child process. */
2181 if (ptychannel >= 0 && p->pty_out)
2182 {
2183 forkout = pty_tty;
2184 p->open_fd[READ_FROM_SUBPROCESS] = inchannel = ptychannel;
2185 }
2186 else
2187 {
2188 if (emacs_pipe (p->open_fd + READ_FROM_SUBPROCESS) != 0)
2189 report_file_error ("Creating pipe", Qnil);
2145 inchannel = p->open_fd[READ_FROM_SUBPROCESS]; 2190 inchannel = p->open_fd[READ_FROM_SUBPROCESS];
2146 forkout = p->open_fd[SUBPROCESS_STDOUT]; 2191 forkout = p->open_fd[SUBPROCESS_STDOUT];
2147 2192
2148#if defined(GNU_LINUX) && defined(F_SETPIPE_SZ) 2193#if defined(GNU_LINUX) && defined(F_SETPIPE_SZ)
2149 fcntl (inchannel, F_SETPIPE_SZ, read_process_output_max); 2194 fcntl (inchannel, F_SETPIPE_SZ, read_process_output_max);
2150#endif 2195#endif
2196 }
2151 2197
2152 if (!NILP (p->stderrproc)) 2198 if (!NILP (p->stderrproc))
2153 { 2199 {
2154 struct Lisp_Process *pp = XPROCESS (p->stderrproc); 2200 struct Lisp_Process *pp = XPROCESS (p->stderrproc);
2155 2201
2156 forkerr = pp->open_fd[SUBPROCESS_STDOUT]; 2202 forkerr = pp->open_fd[SUBPROCESS_STDOUT];
2157 2203
2158 /* Close unnecessary file descriptors. */ 2204 /* Close unnecessary file descriptors. */
2159 close_process_fd (&pp->open_fd[WRITE_TO_SUBPROCESS]); 2205 close_process_fd (&pp->open_fd[WRITE_TO_SUBPROCESS]);
2160 close_process_fd (&pp->open_fd[SUBPROCESS_STDIN]); 2206 close_process_fd (&pp->open_fd[SUBPROCESS_STDIN]);
2161 }
2162 } 2207 }
2163 2208
2164 if (FD_SETSIZE <= inchannel || FD_SETSIZE <= outchannel) 2209 if (FD_SETSIZE <= inchannel || FD_SETSIZE <= outchannel)
@@ -2183,7 +2228,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2183 we just reopen the device (see emacs_get_tty_pgrp) as this is 2228 we just reopen the device (see emacs_get_tty_pgrp) as this is
2184 more portable (see USG_SUBTTY_WORKS above). */ 2229 more portable (see USG_SUBTTY_WORKS above). */
2185 2230
2186 p->pty_flag = pty_flag; 2231 p->pty_in = pty_in;
2232 p->pty_out = pty_out;
2187 pset_status (p, Qrun); 2233 pset_status (p, Qrun);
2188 2234
2189 if (!EQ (p->command, Qt) 2235 if (!EQ (p->command, Qt)
@@ -2199,13 +2245,15 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2199 block_input (); 2245 block_input ();
2200 block_child_signal (&oldset); 2246 block_child_signal (&oldset);
2201 2247
2202 pty_flag = p->pty_flag; 2248 pty_in = p->pty_in;
2203 eassert (pty_flag == ! NILP (lisp_pty_name)); 2249 pty_out = p->pty_out;
2250 eassert ((pty_in || pty_out) == ! NILP (lisp_pty_name));
2204 2251
2205 vfork_errno 2252 vfork_errno
2206 = emacs_spawn (&pid, forkin, forkout, forkerr, new_argv, env, 2253 = emacs_spawn (&pid, forkin, forkout, forkerr, new_argv, env,
2207 SSDATA (current_dir), 2254 SSDATA (current_dir),
2208 pty_flag ? SSDATA (lisp_pty_name) : NULL, &oldset); 2255 pty_in || pty_out ? SSDATA (lisp_pty_name) : NULL,
2256 pty_in, pty_out, &oldset);
2209 2257
2210 eassert ((vfork_errno == 0) == (0 < pid)); 2258 eassert ((vfork_errno == 0) == (0 < pid));
2211 2259
@@ -2263,7 +2311,7 @@ create_pty (Lisp_Object process)
2263{ 2311{
2264 struct Lisp_Process *p = XPROCESS (process); 2312 struct Lisp_Process *p = XPROCESS (process);
2265 char pty_name[PTY_NAME_SIZE]; 2313 char pty_name[PTY_NAME_SIZE];
2266 int pty_fd = !p->pty_flag ? -1 : allocate_pty (pty_name); 2314 int pty_fd = !(p->pty_in || p->pty_out) ? -1 : allocate_pty (pty_name);
2267 2315
2268 if (pty_fd >= 0) 2316 if (pty_fd >= 0)
2269 { 2317 {
@@ -2301,7 +2349,7 @@ create_pty (Lisp_Object process)
2301 we just reopen the device (see emacs_get_tty_pgrp) as this is 2349 we just reopen the device (see emacs_get_tty_pgrp) as this is
2302 more portable (see USG_SUBTTY_WORKS above). */ 2350 more portable (see USG_SUBTTY_WORKS above). */
2303 2351
2304 p->pty_flag = 1; 2352 p->pty_in = p->pty_out = true;
2305 pset_status (p, Qrun); 2353 pset_status (p, Qrun);
2306 setup_process_coding_systems (process); 2354 setup_process_coding_systems (process);
2307 2355
@@ -2412,7 +2460,7 @@ usage: (make-pipe-process &rest ARGS) */)
2412 p->kill_without_query = 1; 2460 p->kill_without_query = 1;
2413 if (tem = plist_get (contact, QCstop), !NILP (tem)) 2461 if (tem = plist_get (contact, QCstop), !NILP (tem))
2414 pset_command (p, Qt); 2462 pset_command (p, Qt);
2415 eassert (! p->pty_flag); 2463 eassert (! p->pty_in && ! p->pty_out);
2416 2464
2417 if (!EQ (p->command, Qt) 2465 if (!EQ (p->command, Qt)
2418 && !EQ (p->filter, Qt)) 2466 && !EQ (p->filter, Qt))
@@ -3147,7 +3195,7 @@ usage: (make-serial-process &rest ARGS) */)
3147 p->kill_without_query = 1; 3195 p->kill_without_query = 1;
3148 if (tem = plist_get (contact, QCstop), !NILP (tem)) 3196 if (tem = plist_get (contact, QCstop), !NILP (tem))
3149 pset_command (p, Qt); 3197 pset_command (p, Qt);
3150 eassert (! p->pty_flag); 3198 eassert (! p->pty_in && ! p->pty_out);
3151 3199
3152 if (!EQ (p->command, Qt) 3200 if (!EQ (p->command, Qt)
3153 && !EQ (p->filter, Qt)) 3201 && !EQ (p->filter, Qt))
@@ -6339,7 +6387,7 @@ Otherwise it discards the output. */)
6339 6387
6340 /* If the restriction isn't what it should be, set it. */ 6388 /* If the restriction isn't what it should be, set it. */
6341 if (old_begv != BEGV || old_zv != ZV) 6389 if (old_begv != BEGV || old_zv != ZV)
6342 Fnarrow_to_region (make_fixnum (old_begv), make_fixnum (old_zv), Qnil); 6390 Fnarrow_to_region (make_fixnum (old_begv), make_fixnum (old_zv));
6343 6391
6344 bset_read_only (current_buffer, old_read_only); 6392 bset_read_only (current_buffer, old_read_only);
6345 SET_PT_BOTH (opoint, opoint_byte); 6393 SET_PT_BOTH (opoint, opoint_byte);
@@ -6808,7 +6856,7 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
6808 error ("Process %s is not active", 6856 error ("Process %s is not active",
6809 SDATA (p->name)); 6857 SDATA (p->name));
6810 6858
6811 if (!p->pty_flag) 6859 if (! p->pty_in)
6812 current_group = Qnil; 6860 current_group = Qnil;
6813 6861
6814 /* If we are using pgrps, get a pgrp number and make it negative. */ 6862 /* If we are using pgrps, get a pgrp number and make it negative. */
@@ -7177,7 +7225,7 @@ process has been transmitted to the serial port. */)
7177 send_process (proc, "", 0, Qnil); 7225 send_process (proc, "", 0, Qnil);
7178 } 7226 }
7179 7227
7180 if (XPROCESS (proc)->pty_flag) 7228 if (XPROCESS (proc)->pty_in)
7181 send_process (proc, "\004", 1, Qnil); 7229 send_process (proc, "\004", 1, Qnil);
7182 else if (EQ (XPROCESS (proc)->type, Qserial)) 7230 else if (EQ (XPROCESS (proc)->type, Qserial))
7183 { 7231 {
diff --git a/src/process.h b/src/process.h
index 392b661ce69..92baf0c4cb9 100644
--- a/src/process.h
+++ b/src/process.h
@@ -156,8 +156,9 @@ struct Lisp_Process
156 /* True means kill silently if Emacs is exited. 156 /* True means kill silently if Emacs is exited.
157 This is the inverse of the `query-on-exit' flag. */ 157 This is the inverse of the `query-on-exit' flag. */
158 bool_bf kill_without_query : 1; 158 bool_bf kill_without_query : 1;
159 /* True if communicating through a pty. */ 159 /* True if communicating through a pty for input or output. */
160 bool_bf pty_flag : 1; 160 bool_bf pty_in : 1;
161 bool_bf pty_out : 1;
161 /* Flag to set coding-system of the process buffer from the 162 /* Flag to set coding-system of the process buffer from the
162 coding_system used to decode process output. */ 163 coding_system used to decode process output. */
163 bool_bf inherit_coding_system_flag : 1; 164 bool_bf inherit_coding_system_flag : 1;
diff --git a/src/puresize.h b/src/puresize.h
index 5516747ac2b..4b746924bb1 100644
--- a/src/puresize.h
+++ b/src/puresize.h
@@ -47,7 +47,7 @@ INLINE_HEADER_BEGIN
47#endif 47#endif
48 48
49#ifndef BASE_PURESIZE 49#ifndef BASE_PURESIZE
50#define BASE_PURESIZE (2000000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) 50#define BASE_PURESIZE (2750000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA)
51#endif 51#endif
52 52
53/* Increase BASE_PURESIZE by a ratio depending on the machine's word size. */ 53/* Increase BASE_PURESIZE by a ratio depending on the machine's word size. */
diff --git a/src/sysdep.c b/src/sysdep.c
index c1545622dfc..efd9638b07a 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -3169,7 +3169,8 @@ list_system_processes (void)
3169 3169
3170#endif /* !defined (WINDOWSNT) */ 3170#endif /* !defined (WINDOWSNT) */
3171 3171
3172#if defined __FreeBSD__ || defined DARWIN_OS || defined __OpenBSD__ 3172#if (HAVE_GETRUSAGE \
3173 || defined __FreeBSD__ || defined DARWIN_OS || defined __OpenBSD__)
3173 3174
3174static Lisp_Object 3175static Lisp_Object
3175make_lisp_s_us (time_t s, long us) 3176make_lisp_s_us (time_t s, long us)
@@ -4276,7 +4277,7 @@ does the same thing as `current-time'. */)
4276 usecs -= 1000000; 4277 usecs -= 1000000;
4277 secs++; 4278 secs++;
4278 } 4279 }
4279 return make_lisp_time (make_timespec (secs, usecs * 1000)); 4280 return make_lisp_s_us (secs, usecs);
4280#else /* ! HAVE_GETRUSAGE */ 4281#else /* ! HAVE_GETRUSAGE */
4281#ifdef WINDOWSNT 4282#ifdef WINDOWSNT
4282 return w32_get_internal_run_time (); 4283 return w32_get_internal_run_time ();
diff --git a/src/timefns.c b/src/timefns.c
index 9df50eaecc3..1112f174763 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -387,9 +387,9 @@ enum { flt_radix_power_size = DBL_MANT_DIG - DBL_MIN_EXP + 1 };
387 equals FLT_RADIX**P. */ 387 equals FLT_RADIX**P. */
388static Lisp_Object flt_radix_power; 388static Lisp_Object flt_radix_power;
389 389
390/* Convert T into an Emacs time *RESULT, truncating toward minus infinity. 390/* Convert the finite number T into an Emacs time *RESULT, truncating
391 Return zero if successful, an error number otherwise. */ 391 toward minus infinity. Signal an error if unsuccessful. */
392static int 392static void
393decode_float_time (double t, struct lisp_time *result) 393decode_float_time (double t, struct lisp_time *result)
394{ 394{
395 Lisp_Object ticks, hz; 395 Lisp_Object ticks, hz;
@@ -401,6 +401,7 @@ decode_float_time (double t, struct lisp_time *result)
401 else 401 else
402 { 402 {
403 int scale = double_integer_scale (t); 403 int scale = double_integer_scale (t);
404 eassume (scale < flt_radix_power_size);
404 405
405 if (scale < 0) 406 if (scale < 0)
406 { 407 {
@@ -412,8 +413,6 @@ decode_float_time (double t, struct lisp_time *result)
412 which is typically better than signaling overflow. */ 413 which is typically better than signaling overflow. */
413 scale = 0; 414 scale = 0;
414 } 415 }
415 else if (flt_radix_power_size <= scale)
416 return isnan (t) ? EDOM : EOVERFLOW;
417 416
418 /* Compute TICKS, HZ such that TICKS / HZ exactly equals T, where HZ is 417 /* Compute TICKS, HZ such that TICKS / HZ exactly equals T, where HZ is
419 T's frequency or 1, whichever is greater. Here, “frequency” means 418 T's frequency or 1, whichever is greater. Here, “frequency” means
@@ -431,7 +430,6 @@ decode_float_time (double t, struct lisp_time *result)
431 } 430 }
432 result->ticks = ticks; 431 result->ticks = ticks;
433 result->hz = hz; 432 result->hz = hz;
434 return 0;
435} 433}
436 434
437/* Make a 4-element timestamp (HI LO US PS) from TICKS and HZ. 435/* Make a 4-element timestamp (HI LO US PS) from TICKS and HZ.
@@ -705,7 +703,7 @@ enum timeform
705 TIMEFORM_TICKS_HZ /* fractional time: HI is ticks, LO is ticks per second */ 703 TIMEFORM_TICKS_HZ /* fractional time: HI is ticks, LO is ticks per second */
706 }; 704 };
707 705
708/* From the valid form FORM and the time components HIGH, LOW, USEC 706/* From the non-float form FORM and the time components HIGH, LOW, USEC
709 and PSEC, generate the corresponding time value. If LOW is 707 and PSEC, generate the corresponding time value. If LOW is
710 floating point, the other components should be zero and FORM should 708 floating point, the other components should be zero and FORM should
711 not be TIMEFORM_TICKS_HZ. 709 not be TIMEFORM_TICKS_HZ.
@@ -734,16 +732,7 @@ decode_time_components (enum timeform form,
734 return EINVAL; 732 return EINVAL;
735 733
736 case TIMEFORM_FLOAT: 734 case TIMEFORM_FLOAT:
737 { 735 eassume (false);
738 double t = XFLOAT_DATA (low);
739 if (result)
740 return decode_float_time (t, result);
741 else
742 {
743 *dresult = t;
744 return 0;
745 }
746 }
747 736
748 case TIMEFORM_NIL: 737 case TIMEFORM_NIL:
749 return decode_ticks_hz (timespec_ticks (current_timespec ()), 738 return decode_ticks_hz (timespec_ticks (current_timespec ()),
@@ -830,7 +819,16 @@ decode_lisp_time (Lisp_Object specified_time, bool decode_secs_only,
830 if (NILP (specified_time)) 819 if (NILP (specified_time))
831 form = TIMEFORM_NIL; 820 form = TIMEFORM_NIL;
832 else if (FLOATP (specified_time)) 821 else if (FLOATP (specified_time))
833 form = TIMEFORM_FLOAT; 822 {
823 double d = XFLOAT_DATA (specified_time);
824 if (!isfinite (d))
825 time_error (isnan (d) ? EDOM : EOVERFLOW);
826 if (result)
827 decode_float_time (d, result);
828 else
829 *dresult = d;
830 return TIMEFORM_FLOAT;
831 }
834 else if (CONSP (specified_time)) 832 else if (CONSP (specified_time))
835 { 833 {
836 high = XCAR (specified_time); 834 high = XCAR (specified_time);
@@ -878,7 +876,7 @@ decode_lisp_time (Lisp_Object specified_time, bool decode_secs_only,
878 return form; 876 return form;
879} 877}
880 878
881/* Convert a Lisp timestamp SPECIFIED_TIME to double. 879/* Convert a non-float Lisp timestamp SPECIFIED_TIME to double.
882 Signal an error if unsuccessful. */ 880 Signal an error if unsuccessful. */
883double 881double
884float_time (Lisp_Object specified_time) 882float_time (Lisp_Object specified_time)
@@ -1074,27 +1072,9 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1074static Lisp_Object 1072static Lisp_Object
1075time_arith (Lisp_Object a, Lisp_Object b, bool subtract) 1073time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1076{ 1074{
1077 if (FLOATP (a) && !isfinite (XFLOAT_DATA (a)))
1078 {
1079 double da = XFLOAT_DATA (a);
1080 double db = float_time (b);
1081 return make_float (subtract ? da - db : da + db);
1082 }
1083 enum timeform aform, bform; 1075 enum timeform aform, bform;
1084 struct lisp_time ta = lisp_time_struct (a, &aform); 1076 struct lisp_time ta = lisp_time_struct (a, &aform);
1085 1077 struct lisp_time tb = lisp_time_struct (b, &bform);
1086 if (FLOATP (b) && !isfinite (XFLOAT_DATA (b)))
1087 return subtract ? make_float (-XFLOAT_DATA (b)) : b;
1088
1089 /* Subtract nil from nil correctly, and handle other eq values
1090 quicker while we're at it. Compare here rather than earlier, to
1091 handle NaNs and check formats. */
1092 struct lisp_time tb;
1093 if (BASE_EQ (a, b))
1094 bform = aform, tb = ta;
1095 else
1096 tb = lisp_time_struct (b, &bform);
1097
1098 Lisp_Object ticks, hz; 1078 Lisp_Object ticks, hz;
1099 1079
1100 if (FASTER_TIMEFNS && BASE_EQ (ta.hz, tb.hz)) 1080 if (FASTER_TIMEFNS && BASE_EQ (ta.hz, tb.hz))
@@ -1201,30 +1181,32 @@ See `format-time-string' for the various forms of a time value.
1201For example, nil stands for the current time. */) 1181For example, nil stands for the current time. */)
1202 (Lisp_Object a, Lisp_Object b) 1182 (Lisp_Object a, Lisp_Object b)
1203{ 1183{
1184 /* Subtract nil from nil correctly, and handle other eq values
1185 quicker while we're at it. This means (time-subtract X X) does
1186 not signal an error if X is not a valid time value, but that's OK. */
1187 if (BASE_EQ (a, b))
1188 return timespec_to_lisp ((struct timespec) {0});
1189
1204 return time_arith (a, b, true); 1190 return time_arith (a, b, true);
1205} 1191}
1206 1192
1207/* Return negative, 0, positive if a < b, a == b, a > b respectively. 1193/* Return negative, 0, positive if A < B, A == B, A > B respectively.
1208 Return positive if either a or b is a NaN; this is good enough 1194 A and B should be Lisp time values. */
1209 for the current callers. */ 1195static EMACS_INT
1210static int
1211time_cmp (Lisp_Object a, Lisp_Object b) 1196time_cmp (Lisp_Object a, Lisp_Object b)
1212{ 1197{
1213 if ((FLOATP (a) && !isfinite (XFLOAT_DATA (a)))
1214 || (FLOATP (b) && !isfinite (XFLOAT_DATA (b))))
1215 {
1216 double da = FLOATP (a) ? XFLOAT_DATA (a) : 0;
1217 double db = FLOATP (b) ? XFLOAT_DATA (b) : 0;
1218 return da < db ? -1 : da != db;
1219 }
1220
1221 /* Compare nil to nil correctly, and handle other eq values quicker 1198 /* Compare nil to nil correctly, and handle other eq values quicker
1222 while we're at it. Compare here rather than earlier, to handle 1199 while we're at it. This means (time-equal-p X X) does not signal
1223 NaNs. This means (time-equal-p X X) does not signal an error if 1200 an error if X is not a valid time value, but that's OK. */
1224 X is not a valid time value, but that's OK. */
1225 if (BASE_EQ (a, b)) 1201 if (BASE_EQ (a, b))
1226 return 0; 1202 return 0;
1227 1203
1204 /* Compare (X . Z) to (Y . Z) quickly if X and Y are fixnums.
1205 Do not inspect Z, as it is OK to not signal if A and B are invalid. */
1206 if (FASTER_TIMEFNS && CONSP (a) && CONSP (b) && BASE_EQ (XCDR (a), XCDR (b))
1207 && FIXNUMP (XCAR (a)) && FIXNUMP (XCAR (b)))
1208 return XFIXNUM (XCAR (a)) - XFIXNUM (XCAR (b));
1209
1228 /* Compare (ATICKS . AZ) to (BTICKS . BHZ) by comparing 1210 /* Compare (ATICKS . AZ) to (BTICKS . BHZ) by comparing
1229 ATICKS * BHZ to BTICKS * AHZ. */ 1211 ATICKS * BHZ to BTICKS * AHZ. */
1230 struct lisp_time ta = lisp_time_struct (a, 0); 1212 struct lisp_time ta = lisp_time_struct (a, 0);
@@ -1258,7 +1240,9 @@ DEFUN ("time-equal-p", Ftime_equal_p, Stime_equal_p, 2, 2, 0,
1258See `format-time-string' for the various forms of a time value. */) 1240See `format-time-string' for the various forms of a time value. */)
1259 (Lisp_Object a, Lisp_Object b) 1241 (Lisp_Object a, Lisp_Object b)
1260{ 1242{
1261 return time_cmp (a, b) == 0 ? Qt : Qnil; 1243 /* A nil arg compares unequal to a non-nil arg. This also saves the
1244 expense of current_timespec if either arg is nil. */
1245 return NILP (a) == NILP (b) && time_cmp (a, b) == 0 ? Qt : Qnil;
1262} 1246}
1263 1247
1264 1248
@@ -1269,11 +1253,12 @@ instead of the current time. See `format-time-string' for the various
1269forms of a time value. 1253forms of a time value.
1270 1254
1271WARNING: Since the result is floating point, it may not be exact. 1255WARNING: Since the result is floating point, it may not be exact.
1272If precise time stamps are required, use either `encode-time', 1256If precise time stamps are required, use either `time-convert',
1273or (if you need time as a string) `format-time-string'. */) 1257or (if you need time as a string) `format-time-string'. */)
1274 (Lisp_Object specified_time) 1258 (Lisp_Object specified_time)
1275{ 1259{
1276 return make_float (float_time (specified_time)); 1260 return (FLOATP (specified_time) ? specified_time
1261 : make_float (float_time (specified_time)));
1277} 1262}
1278 1263
1279/* Write information into buffer S of size MAXSIZE, according to the 1264/* Write information into buffer S of size MAXSIZE, according to the
diff --git a/src/w32fns.c b/src/w32fns.c
index 5e42a1df6ff..28d13a68d45 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -10508,6 +10508,7 @@ frame_parm_handler w32_frame_parm_handlers[] =
10508 0, /* x_set_override_redirect */ 10508 0, /* x_set_override_redirect */
10509 gui_set_no_special_glyphs, 10509 gui_set_no_special_glyphs,
10510 gui_set_alpha_background, 10510 gui_set_alpha_background,
10511 0, /* x_set_use_frame_synchronization */
10511}; 10512};
10512 10513
10513void 10514void
diff --git a/src/xdisp.c b/src/xdisp.c
index 88a489e290f..5268c359ecd 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3229,6 +3229,7 @@ init_iterator (struct it *it, struct window *w,
3229 it->f = XFRAME (w->frame); 3229 it->f = XFRAME (w->frame);
3230 3230
3231 it->cmp_it.id = -1; 3231 it->cmp_it.id = -1;
3232 it->cmp_it.parent_it = it;
3232 3233
3233 if (max_redisplay_ticks > 0) 3234 if (max_redisplay_ticks > 0)
3234 update_redisplay_ticks (0, w); 3235 update_redisplay_ticks (0, w);
@@ -3413,12 +3414,6 @@ init_iterator (struct it *it, struct window *w,
3413 } 3414 }
3414 } 3415 }
3415 3416
3416 if (current_buffer->long_line_optimizations_p)
3417 {
3418 it->narrowed_begv = get_narrowed_begv (w, window_point (w));
3419 it->narrowed_zv = get_narrowed_zv (w, window_point (w));
3420 }
3421
3422 /* If a buffer position was specified, set the iterator there, 3417 /* If a buffer position was specified, set the iterator there,
3423 getting overlays and face properties from that position. */ 3418 getting overlays and face properties from that position. */
3424 if (charpos >= BUF_BEG (current_buffer)) 3419 if (charpos >= BUF_BEG (current_buffer))
@@ -3478,6 +3473,10 @@ init_iterator (struct it *it, struct window *w,
3478 &it->bidi_it); 3473 &it->bidi_it);
3479 } 3474 }
3480 3475
3476 /* This is set only when long_line_optimizations_p is non-zero
3477 for the current buffer. */
3478 it->narrowed_begv = 0;
3479
3481 /* Compute faces etc. */ 3480 /* Compute faces etc. */
3482 reseat (it, it->current.pos, true); 3481 reseat (it, it->current.pos, true);
3483 } 3482 }
@@ -3510,9 +3509,7 @@ ptrdiff_t
3510get_narrowed_begv (struct window *w, ptrdiff_t pos) 3509get_narrowed_begv (struct window *w, ptrdiff_t pos)
3511{ 3510{
3512 int len = get_narrowed_len (w); 3511 int len = get_narrowed_len (w);
3513 ptrdiff_t begv; 3512 return max ((pos / len - 1) * len, BEGV);
3514 begv = max ((pos / len - 1) * len, BEGV);
3515 return begv == BEGV ? 0 : begv;
3516} 3513}
3517 3514
3518ptrdiff_t 3515ptrdiff_t
@@ -4397,16 +4394,16 @@ handle_fontified_prop (struct it *it)
4397 4394
4398 if (current_buffer->long_line_optimizations_p) 4395 if (current_buffer->long_line_optimizations_p)
4399 { 4396 {
4400 ptrdiff_t begv = it->narrowed_begv ? it->narrowed_begv : BEGV; 4397 ptrdiff_t begv = it->narrowed_begv;
4401 ptrdiff_t zv = it->narrowed_zv; 4398 ptrdiff_t zv = it->narrowed_zv;
4402 ptrdiff_t charpos = IT_CHARPOS (*it); 4399 ptrdiff_t charpos = IT_CHARPOS (*it);
4403 if (charpos < begv || charpos > zv) 4400 if (charpos < begv || charpos > zv)
4404 { 4401 {
4405 begv = get_narrowed_begv (it->w, charpos); 4402 begv = get_narrowed_begv (it->w, charpos);
4406 if (!begv) begv = BEGV;
4407 zv = get_narrowed_zv (it->w, charpos); 4403 zv = get_narrowed_zv (it->w, charpos);
4408 } 4404 }
4409 Fnarrow_to_region (make_fixnum (begv), make_fixnum (zv), Qt); 4405 narrow_to_region_internal (make_fixnum (begv), make_fixnum (zv), true);
4406 specbind (Qrestrictions_locked, Qt);
4410 } 4407 }
4411 4408
4412 /* Don't allow Lisp that runs from 'fontification-functions' 4409 /* Don't allow Lisp that runs from 'fontification-functions'
@@ -7416,7 +7413,7 @@ back_to_previous_visible_line_start (struct it *it)
7416 it->continuation_lines_width = 0; 7413 it->continuation_lines_width = 0;
7417 7414
7418 eassert (IT_CHARPOS (*it) >= BEGV); 7415 eassert (IT_CHARPOS (*it) >= BEGV);
7419 eassert (it->narrowed_begv > BEGV 7416 eassert (it->narrowed_begv > 0 /* long-line optimizations: all bets off */
7420 || IT_CHARPOS (*it) == BEGV 7417 || IT_CHARPOS (*it) == BEGV
7421 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n'); 7418 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7422 CHECK_IT (it); 7419 CHECK_IT (it);
@@ -7532,6 +7529,21 @@ reseat (struct it *it, struct text_pos pos, bool force_p)
7532 7529
7533 reseat_1 (it, pos, false); 7530 reseat_1 (it, pos, false);
7534 7531
7532 if (current_buffer->long_line_optimizations_p)
7533 {
7534 if (!it->narrowed_begv)
7535 {
7536 it->narrowed_begv = get_narrowed_begv (it->w, window_point (it->w));
7537 it->narrowed_zv = get_narrowed_zv (it->w, window_point (it->w));
7538 }
7539 else if ((pos.charpos < it->narrowed_begv || pos.charpos > it->narrowed_zv)
7540 && (!redisplaying_p || it->line_wrap == TRUNCATE))
7541 {
7542 it->narrowed_begv = get_narrowed_begv (it->w, pos.charpos);
7543 it->narrowed_zv = get_narrowed_zv (it->w, pos.charpos);
7544 }
7545 }
7546
7535 /* Determine where to check text properties. Avoid doing it 7547 /* Determine where to check text properties. Avoid doing it
7536 where possible because text property lookup is very expensive. */ 7548 where possible because text property lookup is very expensive. */
7537 if (force_p 7549 if (force_p
@@ -8837,7 +8849,7 @@ get_visually_first_element (struct it *it)
8837 8849
8838 SET_WITH_NARROWED_BEGV (it, bob, 8850 SET_WITH_NARROWED_BEGV (it, bob,
8839 string_p ? 0 : 8851 string_p ? 0 :
8840 IT_BYTEPOS (*it) < BEGV ? obegv : BEGV, 8852 IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
8841 it->narrowed_begv); 8853 it->narrowed_begv);
8842 8854
8843 if (STRINGP (it->string)) 8855 if (STRINGP (it->string))
@@ -10699,6 +10711,11 @@ move_it_vertically_backward (struct it *it, int dy)
10699 while (nlines-- && IT_CHARPOS (*it) > pos_limit) 10711 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
10700 back_to_previous_visible_line_start (it); 10712 back_to_previous_visible_line_start (it);
10701 10713
10714 /* Move one line more back, for the (rare) situation where we have
10715 bidi-reordered continued lines, and we start from the top-most
10716 screen line, which is the last in logical order. */
10717 if (it->bidi_p && dy == 0)
10718 back_to_previous_visible_line_start (it);
10702 /* Reseat the iterator here. When moving backward, we don't want 10719 /* Reseat the iterator here. When moving backward, we don't want
10703 reseat to skip forward over invisible text, set up the iterator 10720 reseat to skip forward over invisible text, set up the iterator
10704 to deliver from overlay strings at the new position etc. So, 10721 to deliver from overlay strings at the new position etc. So,
@@ -10772,7 +10789,7 @@ move_it_vertically_backward (struct it *it, int dy)
10772 dec_both (&cp, &bp); 10789 dec_both (&cp, &bp);
10773 SET_WITH_NARROWED_BEGV (it, cp, 10790 SET_WITH_NARROWED_BEGV (it, cp,
10774 find_newline_no_quit (cp, bp, -1, NULL), 10791 find_newline_no_quit (cp, bp, -1, NULL),
10775 it->narrowed_begv); 10792 get_closer_narrowed_begv (it->w, IT_CHARPOS (*it)));
10776 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS); 10793 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10777 } 10794 }
10778 bidi_unshelve_cache (it3data, true); 10795 bidi_unshelve_cache (it3data, true);
@@ -10950,6 +10967,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
10950 position. This may actually move vertically backwards, 10967 position. This may actually move vertically backwards,
10951 in case of overlays, so adjust dvpos accordingly. */ 10968 in case of overlays, so adjust dvpos accordingly. */
10952 dvpos += it->vpos; 10969 dvpos += it->vpos;
10970 start_charpos = IT_CHARPOS (*it);
10953 move_it_vertically_backward (it, 0); 10971 move_it_vertically_backward (it, 0);
10954 dvpos -= it->vpos; 10972 dvpos -= it->vpos;
10955 10973
@@ -11003,7 +11021,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
11003 SAVE_IT (it2, *it, it2data); 11021 SAVE_IT (it2, *it, it2data);
11004 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS); 11022 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
11005 /* Move back again if we got too far ahead. */ 11023 /* Move back again if we got too far ahead. */
11006 if (IT_CHARPOS (*it) >= start_charpos) 11024 if (it->vpos - it2.vpos > delta)
11007 RESTORE_IT (it, &it2, it2data); 11025 RESTORE_IT (it, &it2, it2data);
11008 else 11026 else
11009 bidi_unshelve_cache (it2data, true); 11027 bidi_unshelve_cache (it2data, true);
@@ -18115,8 +18133,8 @@ run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18115 { 18133 {
18116 specpdl_ref count = SPECPDL_INDEX (); 18134 specpdl_ref count = SPECPDL_INDEX ();
18117 specbind (Qinhibit_quit, Qt); 18135 specbind (Qinhibit_quit, Qt);
18118 run_hook_with_args_2 (Qwindow_scroll_functions, window, 18136 safe_run_hooks_2
18119 make_fixnum (CHARPOS (startp))); 18137 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18120 unbind_to (count, Qnil); 18138 unbind_to (count, Qnil);
18121 SET_TEXT_POS_FROM_MARKER (startp, w->start); 18139 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18122 /* In case the hook functions switch buffers. */ 18140 /* In case the hook functions switch buffers. */
@@ -18825,6 +18843,8 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
18825 { 18843 {
18826 /* Cursor has to be moved backward. Note that PT >= 18844 /* Cursor has to be moved backward. Note that PT >=
18827 CHARPOS (startp) because of the outer if-statement. */ 18845 CHARPOS (startp) because of the outer if-statement. */
18846 struct glyph_row *row0 = row;
18847
18828 while (!row->mode_line_p 18848 while (!row->mode_line_p
18829 && (MATRIX_ROW_START_CHARPOS (row) > PT 18849 && (MATRIX_ROW_START_CHARPOS (row) > PT
18830 || (MATRIX_ROW_START_CHARPOS (row) == PT 18850 || (MATRIX_ROW_START_CHARPOS (row) == PT
@@ -18839,6 +18859,23 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
18839 --row; 18859 --row;
18840 } 18860 }
18841 18861
18862 /* With bidi-reordered rows we can have buffer positions
18863 _decrease_ when going down by rows. If we haven't
18864 found our row in the loop above, give it another try
18865 now going in the other direction from the original row. */
18866 if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
18867 && PT <= MATRIX_ROW_END_CHARPOS (row))
18868 && row0->continued_p)
18869 {
18870 row = row0;
18871 while (MATRIX_ROW_START_CHARPOS (row) > PT
18872 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
18873 {
18874 eassert (row->enabled_p);
18875 ++row;
18876 }
18877 }
18878
18842 /* Consider the following case: Window starts at BEGV, 18879 /* Consider the following case: Window starts at BEGV,
18843 there is invisible, intangible text at BEGV, so that 18880 there is invisible, intangible text at BEGV, so that
18844 display starts at some point START > BEGV. It can 18881 display starts at some point START > BEGV. It can
@@ -18862,9 +18899,16 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
18862 && !cursor_row_p (row)) 18899 && !cursor_row_p (row))
18863 ++row; 18900 ++row;
18864 18901
18865 /* If within the scroll margin, scroll. */ 18902 /* If within the scroll margin, either the top one or
18866 if (row->y < top_scroll_margin 18903 the bottom one, scroll. */
18867 && CHARPOS (startp) != BEGV) 18904 if ((row->y < top_scroll_margin
18905 && CHARPOS (startp) != BEGV)
18906 || MATRIX_ROW_BOTTOM_Y (row) > last_y
18907 || PT > MATRIX_ROW_END_CHARPOS (row)
18908 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
18909 && PT == MATRIX_ROW_END_CHARPOS (row)
18910 && !row->ends_at_zv_p
18911 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
18868 scroll_p = true; 18912 scroll_p = true;
18869 } 18913 }
18870 else 18914 else
@@ -19448,7 +19492,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
19448 { 19492 {
19449 ptrdiff_t cur, next, found, max = 0, threshold; 19493 ptrdiff_t cur, next, found, max = 0, threshold;
19450 threshold = XFIXNUM (Vlong_line_threshold); 19494 threshold = XFIXNUM (Vlong_line_threshold);
19451 for (cur = 1; cur < Z; cur = next) 19495 for (cur = BEG; cur < Z; cur = next)
19452 { 19496 {
19453 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1, 19497 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19454 &found, NULL, true); 19498 &found, NULL, true);
diff --git a/src/xfns.c b/src/xfns.c
index 1ae615fad44..2845ecca6a9 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -609,24 +609,24 @@ x_relative_mouse_position (struct frame *f, int *x, int *y)
609 609
610 block_input (); 610 block_input ();
611 611
612 XQueryPointer (FRAME_X_DISPLAY (f), 612 x_query_pointer (FRAME_X_DISPLAY (f),
613 FRAME_DISPLAY_INFO (f)->root_window, 613 FRAME_DISPLAY_INFO (f)->root_window,
614 614
615 /* The root window which contains the pointer. */ 615 /* The root window which contains the pointer. */
616 &root, 616 &root,
617 617
618 /* Window pointer is on, not used */ 618 /* Window pointer is on, not used */
619 &dummy_window, 619 &dummy_window,
620 620
621 /* The position on that root window. */ 621 /* The position on that root window. */
622 x, y, 622 x, y,
623 623
624 /* x/y in dummy_window coordinates, not used. */ 624 /* x/y in dummy_window coordinates, not used. */
625 &dummy, &dummy, 625 &dummy, &dummy,
626 626
627 /* Modifier keys and pointer buttons, about which 627 /* Modifier keys and pointer buttons, about which
628 we don't care. */ 628 we don't care. */
629 (unsigned int *) &dummy); 629 (unsigned int *) &dummy);
630 630
631 XTranslateCoordinates (FRAME_X_DISPLAY (f), 631 XTranslateCoordinates (FRAME_X_DISPLAY (f),
632 632
@@ -1202,20 +1202,6 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1202 xg_set_background_color (f, bg); 1202 xg_set_background_color (f, bg);
1203#endif 1203#endif
1204 1204
1205#ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
1206 toolkit scroll bars. */
1207 {
1208 Lisp_Object bar;
1209 for (bar = FRAME_SCROLL_BARS (f);
1210 !NILP (bar);
1211 bar = XSCROLL_BAR (bar)->next)
1212 {
1213 Window window = XSCROLL_BAR (bar)->x_window;
1214 XSetWindowBackground (dpy, window, bg);
1215 }
1216 }
1217#endif /* USE_TOOLKIT_SCROLL_BARS */
1218
1219 unblock_input (); 1205 unblock_input ();
1220 update_face_from_frame_parameter (f, Qbackground_color, arg); 1206 update_face_from_frame_parameter (f, Qbackground_color, arg);
1221 1207
@@ -2431,6 +2417,28 @@ x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
2431 } 2417 }
2432} 2418}
2433 2419
2420static void
2421x_set_use_frame_synchronization (struct frame *f, Lisp_Object arg,
2422 Lisp_Object oldval)
2423{
2424#if !defined USE_GTK && defined HAVE_XSYNC
2425 struct x_display_info *dpyinfo;
2426
2427 dpyinfo = FRAME_DISPLAY_INFO (f);
2428
2429 if (!NILP (arg) && FRAME_X_EXTENDED_COUNTER (f))
2430 FRAME_X_OUTPUT (f)->use_vsync_p
2431 = x_wm_supports (f, dpyinfo->Xatom_net_wm_frame_drawn);
2432 else
2433 FRAME_X_OUTPUT (f)->use_vsync_p = false;
2434
2435 store_frame_param (f, Quse_frame_synchronization,
2436 FRAME_X_OUTPUT (f)->use_vsync_p ? Qt : Qnil);
2437#else
2438 store_frame_param (f, Quse_frame_synchronization, Qnil);
2439#endif
2440}
2441
2434 2442
2435/* Record in frame F the specified or default value according to ALIST 2443/* Record in frame F the specified or default value according to ALIST
2436 of the parameter named PROP (a Lisp symbol). If no value is 2444 of the parameter named PROP (a Lisp symbol). If no value is
@@ -5149,18 +5157,20 @@ This function is an internal primitive--use `make-frame' instead. */)
5149 (unsigned char *) &counters, 5157 (unsigned char *) &counters,
5150 ((STRINGP (value) 5158 ((STRINGP (value)
5151 && !strcmp (SSDATA (value), "extended")) ? 2 : 1)); 5159 && !strcmp (SSDATA (value), "extended")) ? 2 : 1));
5152#endif
5153 5160
5154#ifndef USE_GTK 5161#if defined HAVE_XSYNCTRIGGERFENCE && !defined USE_GTK
5155 if (FRAME_X_EXTENDED_COUNTER (f)) 5162 x_sync_init_fences (f);
5156 FRAME_X_OUTPUT (f)->use_vsync_p 5163#endif
5157 = x_wm_supports (f, dpyinfo->Xatom_net_wm_frame_drawn);
5158#endif 5164#endif
5159 } 5165 }
5160#endif 5166#endif
5161 5167
5162 unblock_input (); 5168 unblock_input ();
5163 5169
5170 /* Set whether or not frame synchronization is enabled. */
5171 gui_default_parameter (f, parms, Quse_frame_synchronization, Qt,
5172 NULL, NULL, RES_TYPE_BOOLEAN);
5173
5164 /* Works iff frame has been already mapped. */ 5174 /* Works iff frame has been already mapped. */
5165 gui_default_parameter (f, parms, Qskip_taskbar, Qnil, 5175 gui_default_parameter (f, parms, Qskip_taskbar, Qnil,
5166 NULL, NULL, RES_TYPE_BOOLEAN); 5176 NULL, NULL, RES_TYPE_BOOLEAN);
@@ -6813,10 +6823,10 @@ selected frame's display. */)
6813 return Qnil; 6823 return Qnil;
6814 6824
6815 block_input (); 6825 block_input ();
6816 XQueryPointer (FRAME_X_DISPLAY (f), 6826 x_query_pointer (FRAME_X_DISPLAY (f),
6817 FRAME_DISPLAY_INFO (f)->root_window, 6827 FRAME_DISPLAY_INFO (f)->root_window,
6818 &root, &dummy_window, &x, &y, &dummy, &dummy, 6828 &root, &dummy_window, &x, &y, &dummy, &dummy,
6819 (unsigned int *) &dummy); 6829 (unsigned int *) &dummy);
6820 unblock_input (); 6830 unblock_input ();
6821 6831
6822 return Fcons (make_fixnum (x), make_fixnum (y)); 6832 return Fcons (make_fixnum (x), make_fixnum (y));
@@ -8372,8 +8382,8 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx,
8372 Lisp_Object frame, attributes, monitor, geometry; 8382 Lisp_Object frame, attributes, monitor, geometry;
8373 8383
8374 block_input (); 8384 block_input ();
8375 XQueryPointer (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window, 8385 x_query_pointer (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
8376 &root, &child, root_x, root_y, &win_x, &win_y, &pmask); 8386 &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
8377 unblock_input (); 8387 unblock_input ();
8378 8388
8379 XSETFRAME (frame, f); 8389 XSETFRAME (frame, f);
@@ -9775,6 +9785,7 @@ frame_parm_handler x_frame_parm_handlers[] =
9775 x_set_override_redirect, 9785 x_set_override_redirect,
9776 gui_set_no_special_glyphs, 9786 gui_set_no_special_glyphs,
9777 x_set_alpha_background, 9787 x_set_alpha_background,
9788 x_set_use_frame_synchronization,
9778 x_set_shaded, 9789 x_set_shaded,
9779}; 9790};
9780 9791
diff --git a/src/xmenu.c b/src/xmenu.c
index 3be0fb18766..5b8a8f77a2d 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -232,6 +232,7 @@ static void
232x_menu_translate_generic_event (XEvent *event) 232x_menu_translate_generic_event (XEvent *event)
233{ 233{
234 struct x_display_info *dpyinfo; 234 struct x_display_info *dpyinfo;
235 struct xi_device_t *device;
235 XEvent copy; 236 XEvent copy;
236 XIDeviceEvent *xev; 237 XIDeviceEvent *xev;
237 238
@@ -265,6 +266,16 @@ x_menu_translate_generic_event (XEvent *event)
265 copy.xbutton.button = xev->detail; 266 copy.xbutton.button = xev->detail;
266 copy.xbutton.same_screen = True; 267 copy.xbutton.same_screen = True;
267 268
269 device = xi_device_from_id (dpyinfo, xev->deviceid);
270
271 /* I don't know the repercussions of changing
272 device->grab on XI_ButtonPress events, so be safe and
273 only do what is necessary to prevent the grab from
274 being left invalid as XMenuActivate swallows
275 events. */
276 if (device && xev->evtype == XI_ButtonRelease)
277 device->grab &= ~(1 << xev->detail);
278
268 XPutBackEvent (dpyinfo->display, &copy); 279 XPutBackEvent (dpyinfo->display, &copy);
269 280
270 break; 281 break;
@@ -2507,6 +2518,10 @@ pop_down_menu (void *arg)
2507 struct pop_down_menu *data = arg; 2518 struct pop_down_menu *data = arg;
2508 struct frame *f = data->frame; 2519 struct frame *f = data->frame;
2509 XMenu *menu = data->menu; 2520 XMenu *menu = data->menu;
2521#ifdef HAVE_XINPUT2
2522 int i;
2523 struct xi_device_t *device;
2524#endif
2510 2525
2511 block_input (); 2526 block_input ();
2512#ifndef MSDOS 2527#ifndef MSDOS
@@ -2526,6 +2541,17 @@ pop_down_menu (void *arg)
2526 results, and it is a pain to ask which are actually held now. */ 2541 results, and it is a pain to ask which are actually held now. */
2527 FRAME_DISPLAY_INFO (f)->grabbed = 0; 2542 FRAME_DISPLAY_INFO (f)->grabbed = 0;
2528 2543
2544#ifdef HAVE_XINPUT2
2545 /* Likewise for XI grabs when the mouse is released on top of the
2546 menu itself. */
2547
2548 for (i = 0; i < FRAME_DISPLAY_INFO (f)->num_devices; ++i)
2549 {
2550 device = &FRAME_DISPLAY_INFO (f)->devices[i];
2551 device->grab = 0;
2552 }
2553#endif
2554
2529#endif /* HAVE_X_WINDOWS */ 2555#endif /* HAVE_X_WINDOWS */
2530 2556
2531 unblock_input (); 2557 unblock_input ();
diff --git a/src/xsettings.c b/src/xsettings.c
index c29a844e0a8..9c60ff825a4 100644
--- a/src/xsettings.c
+++ b/src/xsettings.c
@@ -964,9 +964,10 @@ read_and_apply_settings (Display_Info *dpyinfo, bool send_event_p)
964#endif 964#endif
965 965
966#ifndef HAVE_PGTK 966#ifndef HAVE_PGTK
967/* Check if EVENT for the display in DPYINFO is XSettings related. */ 967/* Check if EVENT for the display in DPYINFO is XSettings related.
968 Return true if it is, after performing associated side effects. */
968 969
969void 970bool
970xft_settings_event (Display_Info *dpyinfo, const XEvent *event) 971xft_settings_event (Display_Info *dpyinfo, const XEvent *event)
971{ 972{
972 bool check_window_p = false, apply_settings_p = false; 973 bool check_window_p = false, apply_settings_p = false;
@@ -1004,6 +1005,8 @@ xft_settings_event (Display_Info *dpyinfo, const XEvent *event)
1004 1005
1005 if (apply_settings_p) 1006 if (apply_settings_p)
1006 read_and_apply_settings (dpyinfo, true); 1007 read_and_apply_settings (dpyinfo, true);
1008
1009 return check_window_p || apply_settings_p;
1007} 1010}
1008#endif 1011#endif
1009 1012
diff --git a/src/xsettings.h b/src/xsettings.h
index 5e5df37062b..833c2b367dc 100644
--- a/src/xsettings.h
+++ b/src/xsettings.h
@@ -36,7 +36,7 @@ typedef struct pgtk_display_info Display_Info;
36 36
37extern void xsettings_initialize (Display_Info *); 37extern void xsettings_initialize (Display_Info *);
38#ifndef HAVE_PGTK 38#ifndef HAVE_PGTK
39extern void xft_settings_event (Display_Info *, const XEvent *); 39extern bool xft_settings_event (Display_Info *, const XEvent *);
40#endif 40#endif
41extern const char *xsettings_get_system_font (void); 41extern const char *xsettings_get_system_font (void);
42#ifdef USE_LUCID 42#ifdef USE_LUCID
diff --git a/src/xterm.c b/src/xterm.c
index d7d4cb418f3..48f10269dfc 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -997,6 +997,7 @@ static const struct x_atom_ref x_atom_refs[] =
997 ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea) 997 ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea)
998 ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST", Xatom_net_wm_sync_request) 998 ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST", Xatom_net_wm_sync_request)
999 ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST_COUNTER", Xatom_net_wm_sync_request_counter) 999 ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST_COUNTER", Xatom_net_wm_sync_request_counter)
1000 ATOM_REFS_INIT ("_NET_WM_SYNC_FENCES", Xatom_net_wm_sync_fences)
1000 ATOM_REFS_INIT ("_NET_WM_FRAME_DRAWN", Xatom_net_wm_frame_drawn) 1001 ATOM_REFS_INIT ("_NET_WM_FRAME_DRAWN", Xatom_net_wm_frame_drawn)
1001 ATOM_REFS_INIT ("_NET_WM_FRAME_TIMINGS", Xatom_net_wm_frame_timings) 1002 ATOM_REFS_INIT ("_NET_WM_FRAME_TIMINGS", Xatom_net_wm_frame_timings)
1002 ATOM_REFS_INIT ("_NET_WM_USER_TIME", Xatom_net_wm_user_time) 1003 ATOM_REFS_INIT ("_NET_WM_USER_TIME", Xatom_net_wm_user_time)
@@ -2837,8 +2838,8 @@ x_dnd_free_toplevels (bool display_alive)
2837 struct x_client_list_window *last; 2838 struct x_client_list_window *last;
2838 struct x_client_list_window *tem = x_dnd_toplevels; 2839 struct x_client_list_window *tem = x_dnd_toplevels;
2839 ptrdiff_t n_windows, i, buffer_size; 2840 ptrdiff_t n_windows, i, buffer_size;
2840 Window *destroy_windows; 2841 Window *destroy_windows UNINIT;
2841 unsigned long *prev_masks; 2842 unsigned long *prev_masks UNINIT;
2842 specpdl_ref count; 2843 specpdl_ref count;
2843 Display *dpy; 2844 Display *dpy;
2844 struct x_display_info *dpyinfo; 2845 struct x_display_info *dpyinfo;
@@ -2847,10 +2848,6 @@ x_dnd_free_toplevels (bool display_alive)
2847 /* Probably called inside an IO error handler. */ 2848 /* Probably called inside an IO error handler. */
2848 return; 2849 return;
2849 2850
2850 /* Pacify GCC. */
2851 prev_masks = NULL;
2852 destroy_windows = NULL;
2853
2854 if (display_alive) 2851 if (display_alive)
2855 { 2852 {
2856 buffer_size = 1024; 2853 buffer_size = 1024;
@@ -2913,6 +2910,7 @@ x_dnd_free_toplevels (bool display_alive)
2913 2910
2914 if (n_windows) 2911 if (n_windows)
2915 { 2912 {
2913 eassume (dpyinfo);
2916 x_ignore_errors_for_next_request (dpyinfo); 2914 x_ignore_errors_for_next_request (dpyinfo);
2917 2915
2918 for (i = 0; i < n_windows; ++i) 2916 for (i = 0; i < n_windows; ++i)
@@ -4963,15 +4961,6 @@ x_xr_ensure_picture (struct frame *f)
4963} 4961}
4964#endif 4962#endif
4965 4963
4966/* Remove calls to XFlush by defining XFlush to an empty replacement.
4967 Calls to XFlush should be unnecessary because the X output buffer
4968 is flushed automatically as needed by calls to XPending,
4969 XNextEvent, or XWindowEvent according to the XFlush man page.
4970 XTread_socket calls XPending. Removing XFlush improves
4971 performance. */
4972
4973#define XFlush(DISPLAY) (void) 0
4974
4975 4964
4976/*********************************************************************** 4965/***********************************************************************
4977 Debugging 4966 Debugging
@@ -5293,15 +5282,15 @@ xi_populate_device_from_info (struct xi_device_t *xi_device,
5293 * device->num_classes); 5282 * device->num_classes);
5294 values = NULL; 5283 values = NULL;
5295#endif 5284#endif
5296#ifdef HAVE_XINPUT2_2
5297 xi_device->touchpoints = NULL;
5298#endif
5299 5285
5300 xi_device->use = device->use; 5286 xi_device->use = device->use;
5287 xi_device->name = build_string (device->name);
5288 xi_device->attachment = device->attachment;
5289
5301#ifdef HAVE_XINPUT2_2 5290#ifdef HAVE_XINPUT2_2
5291 xi_device->touchpoints = NULL;
5302 xi_device->direct_p = false; 5292 xi_device->direct_p = false;
5303#endif 5293#endif
5304 xi_device->name = build_string (device->name);
5305 5294
5306 for (c = 0; c < device->num_classes; ++c) 5295 for (c = 0; c < device->num_classes; ++c)
5307 { 5296 {
@@ -5405,7 +5394,7 @@ xi_populate_device_from_info (struct xi_device_t *xi_device,
5405static void 5394static void
5406x_cache_xi_devices (struct x_display_info *dpyinfo) 5395x_cache_xi_devices (struct x_display_info *dpyinfo)
5407{ 5396{
5408 int ndevices, actual_devices; 5397 int ndevices, actual_devices, i;
5409 XIDeviceInfo *infos; 5398 XIDeviceInfo *infos;
5410 5399
5411 actual_devices = 0; 5400 actual_devices = 0;
@@ -5422,9 +5411,9 @@ x_cache_xi_devices (struct x_display_info *dpyinfo)
5422 return; 5411 return;
5423 } 5412 }
5424 5413
5425 dpyinfo->devices = xmalloc (sizeof *dpyinfo->devices * ndevices); 5414 dpyinfo->devices = xzalloc (sizeof *dpyinfo->devices * ndevices);
5426 5415
5427 for (int i = 0; i < ndevices; ++i) 5416 for (i = 0; i < ndevices; ++i)
5428 { 5417 {
5429 if (infos[i].enabled) 5418 if (infos[i].enabled)
5430 xi_populate_device_from_info (&dpyinfo->devices[actual_devices++], 5419 xi_populate_device_from_info (&dpyinfo->devices[actual_devices++],
@@ -6617,12 +6606,17 @@ x_if_event (Display *dpy, XEvent *event_return,
6617 current_time = current_timespec (); 6606 current_time = current_timespec ();
6618 target = timespec_add (current_time, timeout); 6607 target = timespec_add (current_time, timeout);
6619 6608
6609 /* Check if an event is already in the queue. If it is, avoid
6610 syncing. */
6611 if (XCheckIfEvent (dpy, event_return, predicate, arg))
6612 return 0;
6613
6620 while (true) 6614 while (true)
6621 { 6615 {
6622 /* Get events into the queue. */ 6616 /* Get events into the queue. */
6623 XSync (dpy, False); 6617 XSync (dpy, False);
6624 6618
6625 /* Check if an event is now in the queue. */ 6619 /* Look for an event again. */
6626 if (XCheckIfEvent (dpy, event_return, predicate, arg)) 6620 if (XCheckIfEvent (dpy, event_return, predicate, arg))
6627 return 0; 6621 return 0;
6628 6622
@@ -6646,6 +6640,61 @@ x_if_event (Display *dpy, XEvent *event_return,
6646 } 6640 }
6647} 6641}
6648 6642
6643/* Return the monotonic time corresponding to the high-resolution
6644 server timestamp TIMESTAMP. Return 0 if the necessary information
6645 is not available. */
6646
6647static uint64_t
6648x_sync_get_monotonic_time (struct x_display_info *dpyinfo,
6649 uint64_t timestamp)
6650{
6651 if (dpyinfo->server_time_monotonic_p)
6652 return timestamp;
6653
6654 /* This means we haven't yet initialized the server time offset. */
6655 if (!dpyinfo->server_time_offset)
6656 return 0;
6657
6658 return timestamp - dpyinfo->server_time_offset;
6659}
6660
6661/* Return the current monotonic time in the same format as a
6662 high-resolution server timestamp. */
6663
6664static uint64_t
6665x_sync_current_monotonic_time (void)
6666{
6667 struct timespec time;
6668
6669 clock_gettime (CLOCK_MONOTONIC, &time);
6670 return time.tv_sec * 1000000 + time.tv_nsec / 1000;
6671}
6672
6673/* Decode a _NET_WM_FRAME_DRAWN message and calculate the time it took
6674 to draw the last frame. */
6675
6676static void
6677x_sync_note_frame_times (struct x_display_info *dpyinfo,
6678 struct frame *f, XEvent *event)
6679{
6680 uint64_t low, high, time;
6681 struct x_output *output;
6682
6683 low = event->xclient.data.l[2];
6684 high = event->xclient.data.l[3];
6685 output = FRAME_X_OUTPUT (f);
6686
6687 time = x_sync_get_monotonic_time (dpyinfo, low | (high << 32));
6688
6689 if (time)
6690 output->last_frame_time = time - output->temp_frame_time;
6691
6692#ifdef FRAME_DEBUG
6693 fprintf (stderr, "Drawing the last frame took: %lu ms (%lu)\n",
6694 output->last_frame_time / 1000, time);
6695#endif
6696}
6697
6649static Bool 6698static Bool
6650x_sync_is_frame_drawn_event (Display *dpy, XEvent *event, 6699x_sync_is_frame_drawn_event (Display *dpy, XEvent *event,
6651 XPointer user_data) 6700 XPointer user_data)
@@ -6689,7 +6738,12 @@ x_sync_wait_for_frame_drawn_event (struct frame *f)
6689 fprintf (stderr, "Warning: compositing manager spent more than 1 second " 6738 fprintf (stderr, "Warning: compositing manager spent more than 1 second "
6690 "drawing a frame. Frame synchronization has been disabled\n"); 6739 "drawing a frame. Frame synchronization has been disabled\n");
6691 FRAME_X_OUTPUT (f)->use_vsync_p = false; 6740 FRAME_X_OUTPUT (f)->use_vsync_p = false;
6741
6742 /* Also change the frame parameter to reflect the new state. */
6743 store_frame_param (f, Quse_frame_synchronization, Qnil);
6692 } 6744 }
6745 else
6746 x_sync_note_frame_times (FRAME_DISPLAY_INFO (f), f, &event);
6693 6747
6694 FRAME_X_WAITING_FOR_DRAW (f) = false; 6748 FRAME_X_WAITING_FOR_DRAW (f) = false;
6695} 6749}
@@ -6735,6 +6789,10 @@ x_sync_update_begin (struct frame *f)
6735 /* Wait for the last frame to be drawn before drawing this one. */ 6789 /* Wait for the last frame to be drawn before drawing this one. */
6736 x_sync_wait_for_frame_drawn_event (f); 6790 x_sync_wait_for_frame_drawn_event (f);
6737 6791
6792 /* Make a note of the time at which we started to draw this
6793 frame. */
6794 FRAME_X_OUTPUT (f)->temp_frame_time = x_sync_current_monotonic_time ();
6795
6738 /* Since Emacs needs a non-urgent redraw, ensure that value % 4 == 6796 /* Since Emacs needs a non-urgent redraw, ensure that value % 4 ==
6739 1. Later, add 3 to create the even counter value. */ 6797 1. Later, add 3 to create the even counter value. */
6740 if (XSyncValueLow32 (value) % 4 == 2) 6798 if (XSyncValueLow32 (value) % 4 == 2)
@@ -6755,6 +6813,85 @@ x_sync_update_begin (struct frame *f)
6755 FRAME_X_COUNTER_VALUE (f)); 6813 FRAME_X_COUNTER_VALUE (f));
6756} 6814}
6757 6815
6816#ifdef HAVE_XSYNCTRIGGERFENCE
6817
6818/* Trigger the sync fence for counter VALUE immediately before a frame
6819 finishes. */
6820
6821static void
6822x_sync_trigger_fence (struct frame *f, XSyncValue value)
6823{
6824 uint64_t n, low, high, idx;
6825
6826 /* Sync fences aren't supported by the X server. */
6827 if (FRAME_DISPLAY_INFO (f)->xsync_major < 3
6828 || (FRAME_DISPLAY_INFO (f)->xsync_major == 3
6829 && FRAME_DISPLAY_INFO (f)->xsync_minor < 1))
6830 return;
6831
6832 low = XSyncValueLow32 (value);
6833 high = XSyncValueHigh32 (value);
6834
6835 n = low | (high << 32);
6836 idx = (n / 4) % 2;
6837
6838#ifdef FRAME_DEBUG
6839 fprintf (stderr, "Triggering synchronization fence: %lu\n", idx);
6840#endif
6841
6842 XSyncTriggerFence (FRAME_X_DISPLAY (f),
6843 FRAME_X_OUTPUT (f)->sync_fences[idx]);
6844}
6845
6846/* Initialize the sync fences on F. */
6847
6848void
6849x_sync_init_fences (struct frame *f)
6850{
6851 struct x_output *output;
6852 struct x_display_info *dpyinfo;
6853
6854 output = FRAME_X_OUTPUT (f);
6855 dpyinfo = FRAME_DISPLAY_INFO (f);
6856
6857 /* Sync fences aren't supported by the X server. */
6858 if (dpyinfo->xsync_major < 3
6859 || (dpyinfo->xsync_major == 3
6860 && dpyinfo->xsync_minor < 1))
6861 return;
6862
6863 output->sync_fences[0]
6864 = XSyncCreateFence (FRAME_X_DISPLAY (f),
6865 /* The drawable given below is only used to
6866 determine the screen on which the fence is
6867 created. */
6868 FRAME_X_WINDOW (f),
6869 False);
6870 output->sync_fences[1]
6871 = XSyncCreateFence (FRAME_X_DISPLAY (f),
6872 FRAME_X_WINDOW (f),
6873 False);
6874
6875 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
6876 dpyinfo->Xatom_net_wm_sync_fences, XA_CARDINAL,
6877 32, PropModeReplace,
6878 (unsigned char *) &output->sync_fences, 2);
6879}
6880
6881static void
6882x_sync_free_fences (struct frame *f)
6883{
6884 if (FRAME_X_OUTPUT (f)->sync_fences[0] != None)
6885 XSyncDestroyFence (FRAME_X_DISPLAY (f),
6886 FRAME_X_OUTPUT (f)->sync_fences[0]);
6887
6888 if (FRAME_X_OUTPUT (f)->sync_fences[1] != None)
6889 XSyncDestroyFence (FRAME_X_DISPLAY (f),
6890 FRAME_X_OUTPUT (f)->sync_fences[1]);
6891}
6892
6893#endif
6894
6758/* Tell the compositing manager that FRAME has been drawn and can be 6895/* Tell the compositing manager that FRAME has been drawn and can be
6759 updated. */ 6896 updated. */
6760 6897
@@ -6787,12 +6924,15 @@ x_sync_update_finish (struct frame *f)
6787 if (overflow) 6924 if (overflow)
6788 XSyncIntToValue (&FRAME_X_COUNTER_VALUE (f), 0); 6925 XSyncIntToValue (&FRAME_X_COUNTER_VALUE (f), 0);
6789 6926
6927 /* Trigger any sync fences if necessary. */
6928#ifdef HAVE_XSYNCTRIGGERFENCE
6929 x_sync_trigger_fence (f, FRAME_X_COUNTER_VALUE (f));
6930#endif
6931
6790 XSyncSetCounter (FRAME_X_DISPLAY (f), 6932 XSyncSetCounter (FRAME_X_DISPLAY (f),
6791 FRAME_X_EXTENDED_COUNTER (f), 6933 FRAME_X_EXTENDED_COUNTER (f),
6792 FRAME_X_COUNTER_VALUE (f)); 6934 FRAME_X_COUNTER_VALUE (f));
6793 6935
6794 /* FIXME: this leads to freezes if the compositing manager crashes
6795 in the meantime. */
6796 if (FRAME_OUTPUT_DATA (f)->use_vsync_p) 6936 if (FRAME_OUTPUT_DATA (f)->use_vsync_p)
6797 FRAME_X_WAITING_FOR_DRAW (f) = true; 6937 FRAME_X_WAITING_FOR_DRAW (f) = true;
6798} 6938}
@@ -6805,6 +6945,8 @@ x_sync_handle_frame_drawn (struct x_display_info *dpyinfo,
6805{ 6945{
6806 if (FRAME_OUTER_WINDOW (f) == message->xclient.window) 6946 if (FRAME_OUTER_WINDOW (f) == message->xclient.window)
6807 FRAME_X_WAITING_FOR_DRAW (f) = false; 6947 FRAME_X_WAITING_FOR_DRAW (f) = false;
6948
6949 x_sync_note_frame_times (dpyinfo, f, message);
6808} 6950}
6809#endif 6951#endif
6810 6952
@@ -7388,6 +7530,9 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
7388#ifndef USE_GTK 7530#ifndef USE_GTK
7389 struct frame *focus_frame; 7531 struct frame *focus_frame;
7390 Time old_time; 7532 Time old_time;
7533#if defined HAVE_XSYNC
7534 uint64_t monotonic_time;
7535#endif
7391 7536
7392 focus_frame = dpyinfo->x_focus_frame; 7537 focus_frame = dpyinfo->x_focus_frame;
7393 old_time = dpyinfo->last_user_time; 7538 old_time = dpyinfo->last_user_time;
@@ -7400,6 +7545,28 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
7400 if (!send_event || time > dpyinfo->last_user_time) 7545 if (!send_event || time > dpyinfo->last_user_time)
7401 dpyinfo->last_user_time = time; 7546 dpyinfo->last_user_time = time;
7402 7547
7548#if defined HAVE_XSYNC && !defined USE_GTK
7549 if (!send_event)
7550 {
7551 /* See if the current CLOCK_MONOTONIC time is reasonably close
7552 to the X server time. */
7553 monotonic_time = x_sync_current_monotonic_time ();
7554
7555 if (time * 1000 > monotonic_time - 500 * 1000
7556 && time * 1000 < monotonic_time + 500 * 1000)
7557 dpyinfo->server_time_monotonic_p = true;
7558 else
7559 {
7560 /* Compute an offset that can be subtracted from the server
7561 time to estimate the monotonic time on the X server. */
7562
7563 dpyinfo->server_time_monotonic_p = false;
7564 dpyinfo->server_time_offset
7565 = ((int64_t) time * 1000) - monotonic_time;
7566 }
7567 }
7568#endif
7569
7403#ifndef USE_GTK 7570#ifndef USE_GTK
7404 /* Don't waste bandwidth if the time hasn't actually changed. */ 7571 /* Don't waste bandwidth if the time hasn't actually changed. */
7405 if (focus_frame && old_time != dpyinfo->last_user_time) 7572 if (focus_frame && old_time != dpyinfo->last_user_time)
@@ -7419,6 +7586,26 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
7419#endif 7586#endif
7420} 7587}
7421 7588
7589#ifdef USE_GTK
7590
7591static void
7592x_set_gtk_user_time (struct frame *f, Time time)
7593{
7594 GtkWidget *widget;
7595 GdkWindow *window;
7596
7597 widget = FRAME_GTK_OUTER_WIDGET (f);
7598 window = gtk_widget_get_window (widget);
7599
7600 /* This widget isn't realized yet. */
7601 if (!window)
7602 return;
7603
7604 gdk_x11_window_set_user_time (window, time);
7605}
7606
7607#endif
7608
7422/* Not needed on GTK because GTK handles reporting the user time 7609/* Not needed on GTK because GTK handles reporting the user time
7423 itself. */ 7610 itself. */
7424 7611
@@ -9308,9 +9495,7 @@ x_composite_image (struct glyph_string *s, Pixmap dest,
9308 { 9495 {
9309 Picture destination; 9496 Picture destination;
9310 XRenderPictFormat *default_format; 9497 XRenderPictFormat *default_format;
9311 XRenderPictureAttributes attr; 9498 XRenderPictureAttributes attr UNINIT;
9312 /* Pacify GCC. */
9313 memset (&attr, 0, sizeof attr);
9314 9499
9315 default_format = FRAME_X_PICTURE_FORMAT (s->f); 9500 default_format = FRAME_X_PICTURE_FORMAT (s->f);
9316 destination = XRenderCreatePicture (display, dest, 9501 destination = XRenderCreatePicture (display, dest,
@@ -10466,16 +10651,12 @@ x_clear_frame (struct frame *f)
10466 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); 10651 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
10467 10652
10468 block_input (); 10653 block_input ();
10469
10470 font_drop_xrender_surfaces (f); 10654 font_drop_xrender_surfaces (f);
10471 x_clear_window (f); 10655 x_clear_window (f);
10472 10656
10473 /* We have to clear the scroll bars. If we have changed colors or 10657 /* We have to clear the scroll bars. If we have changed colors or
10474 something like that, then they should be notified. */ 10658 something like that, then they should be notified. */
10475 x_scroll_bar_clear (f); 10659 x_scroll_bar_clear (f);
10476
10477 XFlush (FRAME_X_DISPLAY (f));
10478
10479 unblock_input (); 10660 unblock_input ();
10480} 10661}
10481 10662
@@ -10853,7 +11034,6 @@ x_scroll_run (struct window *w, struct run *run)
10853 view->clip_bottom - view->clip_top); 11034 view->clip_bottom - view->clip_top);
10854 } 11035 }
10855 xwidget_expose (view); 11036 xwidget_expose (view);
10856 XFlush (dpy);
10857 } 11037 }
10858 } 11038 }
10859 } 11039 }
@@ -12286,6 +12466,459 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
12286 return unbind_to (base, Qnil); 12466 return unbind_to (base, Qnil);
12287} 12467}
12288 12468
12469#ifdef HAVE_XINPUT2
12470
12471/* Since the input extension assigns a keyboard focus to each master
12472 device, there is no longer a 1:1 correspondence between the
12473 selected frame and the focus frame immediately after the keyboard
12474 focus is switched to a given frame. This situation is handled by
12475 keeping track of each master device's focus frame, the time of the
12476 last interaction with that frame, and always keeping the focus on
12477 the most recently selected frame. We also use the pointer of the
12478 device that is keeping the current frame focused in functions like
12479 `mouse-position'. */
12480
12481static void
12482xi_handle_focus_change (struct x_display_info *dpyinfo)
12483{
12484 struct input_event ie;
12485 struct frame *focus, *new;
12486 struct xi_device_t *device, *source = NULL;
12487 ptrdiff_t i;
12488 Time time;
12489#ifdef USE_GTK
12490 struct x_output *output;
12491 GtkWidget *widget;
12492#endif
12493
12494 focus = dpyinfo->x_focus_frame;
12495 new = NULL;
12496 time = 0;
12497
12498 dpyinfo->client_pointer_device = -1;
12499
12500 for (i = 0; i < dpyinfo->num_devices; ++i)
12501 {
12502 device = &dpyinfo->devices[i];
12503
12504 if (device->focus_frame
12505 && device->focus_frame_time > time)
12506 {
12507 new = device->focus_frame;
12508 time = device->focus_frame_time;
12509 source = device;
12510
12511 /* Use this device for future calls to `mouse-position' etc.
12512 If it is a keyboard, use its attached pointer. */
12513
12514 if (device->use == XIMasterKeyboard)
12515 dpyinfo->client_pointer_device = device->attachment;
12516 else
12517 dpyinfo->client_pointer_device = device->device_id;
12518 }
12519
12520 if (device->focus_implicit_frame
12521 && device->focus_implicit_time > time)
12522 {
12523 new = device->focus_implicit_frame;
12524 time = device->focus_implicit_time;
12525 source = device;
12526
12527 /* Use this device for future calls to `mouse-position' etc.
12528 If it is a keyboard, use its attached pointer. */
12529
12530 if (device->use == XIMasterKeyboard)
12531 dpyinfo->client_pointer_device = device->attachment;
12532 else
12533 dpyinfo->client_pointer_device = device->device_id;
12534 }
12535 }
12536
12537 if (new != focus && focus)
12538 {
12539#ifdef HAVE_X_I18N
12540 if (FRAME_XIC (focus))
12541 XUnsetICFocus (FRAME_XIC (focus));
12542#endif
12543
12544#ifdef USE_GTK
12545 output = FRAME_X_OUTPUT (focus);
12546
12547 if (x_gtk_use_native_input)
12548 {
12549 gtk_im_context_focus_out (output->im_context);
12550 gtk_im_context_set_client_window (output->im_context,
12551 NULL);
12552 }
12553#endif
12554
12555 EVENT_INIT (ie);
12556 ie.kind = FOCUS_OUT_EVENT;
12557 XSETFRAME (ie.frame_or_window, focus);
12558
12559 kbd_buffer_store_event (&ie);
12560 }
12561
12562 if (new != focus && new)
12563 {
12564#ifdef HAVE_X_I18N
12565 if (FRAME_XIC (new))
12566 XSetICFocus (FRAME_XIC (new));
12567#endif
12568
12569#ifdef USE_GTK
12570 output = FRAME_X_OUTPUT (new);
12571
12572 if (x_gtk_use_native_input)
12573 {
12574 widget = FRAME_GTK_OUTER_WIDGET (new);
12575
12576 gtk_im_context_focus_in (output->im_context);
12577 gtk_im_context_set_client_window (output->im_context,
12578 gtk_widget_get_window (widget));
12579 }
12580#endif
12581
12582 EVENT_INIT (ie);
12583 ie.kind = FOCUS_IN_EVENT;
12584 ie.device = source->name;
12585 XSETFRAME (ie.frame_or_window, new);
12586
12587 kbd_buffer_store_event (&ie);
12588 }
12589
12590 x_new_focus_frame (dpyinfo, new);
12591}
12592
12593static void
12594xi_focus_handle_for_device (struct x_display_info *dpyinfo,
12595 struct frame *mentioned_frame,
12596 XIEvent *base_event)
12597{
12598 struct xi_device_t *device;
12599 XIEnterEvent *event;
12600
12601 /* XILeaveEvent, XIFocusInEvent, etc are just synonyms for
12602 XIEnterEvent. */
12603 event = (XIEnterEvent *) base_event;
12604 device = xi_device_from_id (dpyinfo, event->deviceid);
12605
12606 if (!device)
12607 return;
12608
12609 switch (event->evtype)
12610 {
12611 case XI_FocusIn:
12612 device->focus_frame = mentioned_frame;
12613 device->focus_frame_time = event->time;
12614 break;
12615
12616 case XI_FocusOut:
12617 device->focus_frame = NULL;
12618 break;
12619
12620 case XI_Enter:
12621 if (!event->focus)
12622 break;
12623
12624 if (device->use == XIMasterPointer)
12625 device = xi_device_from_id (dpyinfo, device->attachment);
12626
12627 if (!device)
12628 break;
12629
12630 device->focus_implicit_frame = mentioned_frame;
12631 device->focus_implicit_time = event->time;
12632 break;
12633
12634 case XI_Leave:
12635 if (!event->focus)
12636 break;
12637
12638 if (device->use == XIMasterPointer)
12639 device = xi_device_from_id (dpyinfo, device->attachment);
12640
12641 if (!device)
12642 break;
12643
12644 device->focus_implicit_frame = NULL;
12645 break;
12646 }
12647
12648 xi_handle_focus_change (dpyinfo);
12649}
12650
12651static void
12652xi_handle_delete_frame (struct x_display_info *dpyinfo,
12653 struct frame *f)
12654{
12655 struct xi_device_t *device;
12656 ptrdiff_t i;
12657
12658 for (i = 0; i < dpyinfo->num_devices; ++i)
12659 {
12660 device = &dpyinfo->devices[i];
12661
12662 if (device->focus_frame == f)
12663 device->focus_frame = NULL;
12664
12665 if (device->focus_implicit_frame == f)
12666 device->focus_implicit_frame = NULL;
12667 }
12668}
12669
12670/* Handle an interaction by DEVICE on frame F. TIME is the time of
12671 the interaction; if F isn't currently the global focus frame, but
12672 is the focus of DEVICE, make it the focus frame. */
12673
12674static void
12675xi_handle_interaction (struct x_display_info *dpyinfo,
12676 struct frame *f, struct xi_device_t *device,
12677 Time time)
12678{
12679 bool change;
12680
12681 /* If DEVICE is a pointer, use its attached keyboard device. */
12682 if (device->use == XIMasterPointer)
12683 device = xi_device_from_id (dpyinfo, device->attachment);
12684
12685 if (!device)
12686 return;
12687
12688 change = false;
12689
12690 if (device->focus_frame == f)
12691 {
12692 device->focus_frame_time = time;
12693 change = true;
12694 }
12695
12696 if (device->focus_implicit_frame == f)
12697 {
12698 device->focus_implicit_time = time;
12699 change = true;
12700 }
12701
12702 /* If F isn't currently focused, update the focus state. */
12703 if (change && f != dpyinfo->x_focus_frame)
12704 xi_handle_focus_change (dpyinfo);
12705}
12706
12707#ifdef HAVE_XINPUT2_1
12708
12709/* Look up a scroll valuator in DEVICE by NUMBER. */
12710
12711static struct xi_scroll_valuator_t *
12712xi_get_scroll_valuator (struct xi_device_t *device, int number)
12713{
12714 int i;
12715
12716 for (i = 0; i < device->scroll_valuator_count; ++i)
12717 {
12718 if (device->valuators[i].number == number)
12719 return &device->valuators[i];
12720 }
12721
12722 return NULL;
12723}
12724
12725#endif
12726
12727/* Handle EVENT, a DeviceChanged event. Look up the device that
12728 changed, and update its information with the data in EVENT. */
12729
12730static void
12731xi_handle_device_changed (struct x_display_info *dpyinfo,
12732 struct xi_device_t *device,
12733 XIDeviceChangedEvent *event)
12734{
12735#ifdef HAVE_XINPUT2_1
12736 XIDeviceInfo *info;
12737 XIScrollClassInfo *scroll;
12738 int i, ndevices;
12739 struct xi_scroll_valuator_t *valuator;
12740 XIValuatorClassInfo *valuator_info;
12741#endif
12742#ifdef HAVE_XINPUT2_2
12743 struct xi_touch_point_t *tem, *last;
12744 XITouchClassInfo *touch;
12745#endif
12746
12747#ifdef HAVE_XINPUT2_1
12748 /* When a DeviceChange event is received for a master device, we
12749 don't get any scroll valuators along with it. This is possibly
12750 an X server bug but I really don't want to dig any further, so
12751 fetch the scroll valuators manually. (bug#57020) */
12752
12753 x_catch_errors (dpyinfo->display);
12754 info = XIQueryDevice (dpyinfo->display, event->deviceid,
12755 /* ndevices is always 1 if a deviceid is
12756 specified. If the request fails, NULL will
12757 be returned. */
12758 &ndevices);
12759 x_uncatch_errors ();
12760
12761 if (info)
12762 {
12763 device->valuators = xrealloc (device->valuators,
12764 (info->num_classes
12765 * sizeof *device->valuators));
12766 device->scroll_valuator_count = 0;
12767#ifdef HAVE_XINPUT2_2
12768 device->direct_p = false;
12769#endif
12770
12771 for (i = 0; i < info->num_classes; ++i)
12772 {
12773 switch (info->classes[i]->type)
12774 {
12775 case XIScrollClass:
12776 scroll = (XIScrollClassInfo *) info->classes[i];
12777
12778 valuator = &device->valuators[device->scroll_valuator_count++];
12779 valuator->horizontal = (scroll->scroll_type
12780 == XIScrollTypeHorizontal);
12781 valuator->invalid_p = true;
12782 valuator->emacs_value = DBL_MIN;
12783 valuator->increment = scroll->increment;
12784 valuator->number = scroll->number;
12785 break;
12786
12787#ifdef HAVE_XINPUT2_2
12788 case XITouchClass:
12789 touch = (XITouchClassInfo *) info->classes[i];
12790
12791 if (touch->mode == XIDirectTouch)
12792 device->direct_p = true;
12793 break;
12794#endif
12795 }
12796 }
12797
12798 /* Restore the values of any scroll valuators that we already
12799 know about. */
12800
12801 for (i = 0; i < info->num_classes; ++i)
12802 {
12803 switch (info->classes[i]->type)
12804 {
12805 case XIValuatorClass:
12806 valuator_info = (XIValuatorClassInfo *) info->classes[i];
12807
12808 valuator = xi_get_scroll_valuator (device,
12809 valuator_info->number);
12810 if (valuator)
12811 {
12812 valuator->invalid_p = false;
12813 valuator->current_value = valuator_info->value;
12814
12815 /* Make sure that this is reset if the pointer moves
12816 into a window of ours.
12817
12818 Otherwise the valuator state could be left
12819 invalid if the DeviceChange event happened with
12820 the pointer outside any Emacs frame. */
12821 valuator->pending_enter_reset = true;
12822 }
12823
12824 break;
12825 }
12826 }
12827
12828#ifdef HAVE_XINPUT2_2
12829 /* The device is no longer a DirectTouch device, so
12830 remove any touchpoints that we might have
12831 recorded. */
12832 if (!device->direct_p)
12833 {
12834 tem = device->touchpoints;
12835
12836 while (tem)
12837 {
12838 last = tem;
12839 tem = tem->next;
12840 xfree (last);
12841 }
12842
12843 device->touchpoints = NULL;
12844 }
12845#endif
12846
12847 XIFreeDeviceInfo (info);
12848 }
12849#endif
12850}
12851
12852/* Remove the client-side record of every device in TO_DISABLE.
12853 Called while processing XI_HierarchyChanged events. We batch up
12854 multiple disabled devices because it is more efficient to disable
12855 them at once. */
12856
12857static void
12858xi_disable_devices (struct x_display_info *dpyinfo,
12859 int *to_disable, int n_disabled)
12860{
12861 struct xi_device_t *devices;
12862 int ndevices, i, j;
12863#ifdef HAVE_XINPUT2_2
12864 struct xi_touch_point_t *tem, *last;
12865#endif
12866
12867 /* Don't pointlessly copy dpyinfo->devices if there are no devices
12868 to disable. */
12869 if (!n_disabled)
12870 return;
12871
12872 ndevices = 0;
12873 devices = xzalloc (sizeof *devices * dpyinfo->num_devices);
12874
12875 /* Loop through every device currently in DPYINFO, and copy it to
12876 DEVICES if it is not in TO_DISABLE. Note that this function
12877 should be called with input blocked, since xfree can otherwise
12878 call GC, which will call mark_xterm with invalid state. */
12879 for (i = 0; i < dpyinfo->num_devices; ++i)
12880 {
12881 for (j = 0; j < n_disabled; ++j)
12882 {
12883 if (to_disable[j] == dpyinfo->devices[i].device_id)
12884 {
12885 /* Free any scroll valuators that might be on this
12886 device. */
12887#ifdef HAVE_XINPUT2_1
12888 xfree (dpyinfo->devices[i].valuators);
12889#endif
12890
12891 /* Free any currently active touch points on this
12892 device. */
12893#ifdef HAVE_XINPUT2_2
12894 tem = dpyinfo->devices[i].touchpoints;
12895 while (tem)
12896 {
12897 last = tem;
12898 tem = tem->next;
12899 xfree (last);
12900 }
12901#endif
12902
12903 goto out;
12904 }
12905
12906 devices[ndevices++] = dpyinfo->devices[i];
12907
12908 out:
12909 continue;
12910 }
12911 }
12912
12913 /* Free the old devices array and replace it with ndevices. */
12914 xfree (dpyinfo->devices);
12915
12916 dpyinfo->devices = devices;
12917 dpyinfo->num_devices = ndevices;
12918}
12919
12920#endif
12921
12289/* The focus may have changed. Figure out if it is a real focus change, 12922/* The focus may have changed. Figure out if it is a real focus change,
12290 by checking both FocusIn/Out and Enter/LeaveNotify events. 12923 by checking both FocusIn/Out and Enter/LeaveNotify events.
12291 12924
@@ -12316,37 +12949,6 @@ x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
12316 } 12949 }
12317 break; 12950 break;
12318 12951
12319#ifdef HAVE_XINPUT2
12320 case GenericEvent:
12321 {
12322 XIEvent *xi_event = event->xcookie.data;
12323 XIEnterEvent *enter_or_focus = event->xcookie.data;
12324
12325 struct frame *focus_frame = dpyinfo->x_focus_event_frame;
12326 int focus_state
12327 = focus_frame ? focus_frame->output_data.x->focus_state : 0;
12328
12329 if (xi_event->evtype == XI_FocusIn
12330 || xi_event->evtype == XI_FocusOut)
12331 x_focus_changed ((xi_event->evtype == XI_FocusIn
12332 ? FocusIn : FocusOut),
12333 ((enter_or_focus->detail
12334 == XINotifyPointer)
12335 ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
12336 dpyinfo, frame, bufp);
12337 else if ((xi_event->evtype == XI_Enter
12338 || xi_event->evtype == XI_Leave)
12339 && (enter_or_focus->detail != XINotifyInferior)
12340 && enter_or_focus->focus
12341 && !(focus_state & FOCUS_EXPLICIT))
12342 x_focus_changed ((xi_event->evtype == XI_Enter
12343 ? FocusIn : FocusOut),
12344 FOCUS_IMPLICIT,
12345 dpyinfo, frame, bufp);
12346 break;
12347 }
12348#endif
12349
12350 case FocusIn: 12952 case FocusIn:
12351 case FocusOut: 12953 case FocusOut:
12352 /* Ignore transient focus events from hotkeys, window manager 12954 /* Ignore transient focus events from hotkeys, window manager
@@ -12692,6 +13294,68 @@ get_keysym_name (int keysym)
12692 return value; 13294 return value;
12693} 13295}
12694 13296
13297/* Like XQueryPointer, but always use the right client pointer
13298 device. */
13299
13300Bool
13301x_query_pointer (Display *dpy, Window w, Window *root_return,
13302 Window *child_return, int *root_x_return,
13303 int *root_y_return, int *win_x_return,
13304 int *win_y_return, unsigned int *mask_return)
13305{
13306 Bool rc;
13307#ifdef HAVE_XINPUT2
13308 struct x_display_info *dpyinfo;
13309 bool had_errors;
13310 XIModifierState modifiers;
13311 XIButtonState buttons;
13312 XIGroupState group; /* Unused. */
13313 double root_x, root_y, win_x, win_y;
13314 unsigned int state;
13315#endif
13316
13317#ifdef HAVE_XINPUT2
13318 dpyinfo = x_display_info_for_display (dpy);
13319 if (dpyinfo && dpyinfo->client_pointer_device != -1)
13320 {
13321 /* Catch errors caused by the device going away. This is not
13322 very expensive, since XIQueryPointer will sync anyway. */
13323 x_catch_errors (dpy);
13324 rc = XIQueryPointer (dpyinfo->display,
13325 dpyinfo->client_pointer_device,
13326 w, root_return, child_return,
13327 &root_x, &root_y, &win_x, &win_y,
13328 &buttons, &modifiers, &group);
13329 had_errors = x_had_errors_p (dpy);
13330 x_uncatch_errors_after_check ();
13331
13332 if (had_errors)
13333 rc = XQueryPointer (dpyinfo->display, w, root_return,
13334 child_return, root_x_return,
13335 root_y_return, win_x_return,
13336 win_y_return, mask_return);
13337 else
13338 {
13339 state = 0;
13340
13341 xi_convert_button_state (&buttons, &state);
13342 *mask_return = state | modifiers.effective;
13343
13344 *root_x_return = lrint (root_x);
13345 *root_y_return = lrint (root_y);
13346 *win_x_return = lrint (win_x);
13347 *win_y_return = lrint (win_y);
13348 }
13349 }
13350 else
13351#endif
13352 rc = XQueryPointer (dpy, w, root_return, child_return,
13353 root_x_return, root_y_return, win_x_return,
13354 win_y_return, mask_return);
13355
13356 return rc;
13357}
13358
12695/* Mouse clicks and mouse movement. Rah. 13359/* Mouse clicks and mouse movement. Rah.
12696 13360
12697 Formerly, we used PointerMotionHintMask (in standard_event_mask) 13361 Formerly, we used PointerMotionHintMask (in standard_event_mask)
@@ -12958,20 +13622,20 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
12958 dpyinfo->last_mouse_scroll_bar = NULL; 13622 dpyinfo->last_mouse_scroll_bar = NULL;
12959 13623
12960 /* Figure out which root window we're on. */ 13624 /* Figure out which root window we're on. */
12961 XQueryPointer (FRAME_X_DISPLAY (*fp), 13625 x_query_pointer (FRAME_X_DISPLAY (*fp),
12962 DefaultRootWindow (FRAME_X_DISPLAY (*fp)), 13626 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
12963 /* The root window which contains the pointer. */ 13627 /* The root window which contains the pointer. */
12964 &root, 13628 &root,
12965 /* Trash which we can't trust if the pointer is on 13629 /* Trash which we can't trust if the pointer is on
12966 a different screen. */ 13630 a different screen. */
12967 &dummy_window, 13631 &dummy_window,
12968 /* The position on that root window. */ 13632 /* The position on that root window. */
12969 &root_x, &root_y, 13633 &root_x, &root_y,
12970 /* More trash we can't trust. */ 13634 /* More trash we can't trust. */
12971 &dummy, &dummy, 13635 &dummy, &dummy,
12972 /* Modifier keys and pointer buttons, about which 13636 /* Modifier keys and pointer buttons, about which
12973 we don't care. */ 13637 we don't care. */
12974 (unsigned int *) &dummy); 13638 (unsigned int *) &dummy);
12975 13639
12976 /* Now we have a position on the root; find the innermost window 13640 /* Now we have a position on the root; find the innermost window
12977 containing the pointer. */ 13641 containing the pointer. */
@@ -13206,6 +13870,37 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
13206 13870
13207/* Scroll bar support. */ 13871/* Scroll bar support. */
13208 13872
13873#if defined HAVE_XINPUT2
13874
13875/* Select for input extension events used by scroll bars. This will
13876 result in the corresponding core events not being generated for
13877 SCROLL_BAR. */
13878
13879MAYBE_UNUSED static void
13880xi_select_scroll_bar_events (struct x_display_info *dpyinfo,
13881 Window scroll_bar)
13882{
13883 XIEventMask mask;
13884 unsigned char *m;
13885 ptrdiff_t length;
13886
13887 length = XIMaskLen (XI_LASTEVENT);
13888 mask.mask = m = alloca (length);
13889 memset (m, 0, length);
13890 mask.mask_len = length;
13891
13892 mask.deviceid = XIAllMasterDevices;
13893 XISetMask (m, XI_ButtonPress);
13894 XISetMask (m, XI_ButtonRelease);
13895 XISetMask (m, XI_Motion);
13896 XISetMask (m, XI_Enter);
13897 XISetMask (m, XI_Leave);
13898
13899 XISelectEvents (dpyinfo->display, scroll_bar, &mask, 1);
13900}
13901
13902#endif
13903
13209/* Given an X window ID and a DISPLAY, find the struct scroll_bar which 13904/* Given an X window ID and a DISPLAY, find the struct scroll_bar which
13210 manages it. 13905 manages it.
13211 This can be called in GC, so we have to make sure to strip off mark 13906 This can be called in GC, so we have to make sure to strip off mark
@@ -13996,25 +14691,8 @@ x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
13996 /* Ask for input extension button and motion events. This lets us 14691 /* Ask for input extension button and motion events. This lets us
13997 send the proper `wheel-up' or `wheel-down' events to Emacs. */ 14692 send the proper `wheel-up' or `wheel-down' events to Emacs. */
13998 if (FRAME_DISPLAY_INFO (f)->supports_xi2) 14693 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
13999 { 14694 xi_select_scroll_bar_events (FRAME_DISPLAY_INFO (f),
14000 XIEventMask mask; 14695 XtWindow (widget));
14001 ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
14002 unsigned char *m;
14003
14004 mask.mask = m = alloca (l);
14005 memset (m, 0, l);
14006 mask.mask_len = l;
14007
14008 mask.deviceid = XIAllMasterDevices;
14009 XISetMask (m, XI_ButtonPress);
14010 XISetMask (m, XI_ButtonRelease);
14011 XISetMask (m, XI_Motion);
14012 XISetMask (m, XI_Enter);
14013 XISetMask (m, XI_Leave);
14014
14015 XISelectEvents (XtDisplay (widget), XtWindow (widget),
14016 &mask, 1);
14017 }
14018#endif 14696#endif
14019#else /* !USE_MOTIF i.e. use Xaw */ 14697#else /* !USE_MOTIF i.e. use Xaw */
14020 14698
@@ -14221,25 +14899,8 @@ x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
14221 /* Ask for input extension button and motion events. This lets us 14899 /* Ask for input extension button and motion events. This lets us
14222 send the proper `wheel-up' or `wheel-down' events to Emacs. */ 14900 send the proper `wheel-up' or `wheel-down' events to Emacs. */
14223 if (FRAME_DISPLAY_INFO (f)->supports_xi2) 14901 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
14224 { 14902 xi_select_scroll_bar_events (FRAME_DISPLAY_INFO (f),
14225 XIEventMask mask; 14903 XtWindow (widget));
14226 ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
14227 unsigned char *m;
14228
14229 mask.mask = m = alloca (l);
14230 memset (m, 0, l);
14231 mask.mask_len = l;
14232
14233 mask.deviceid = XIAllMasterDevices;
14234 XISetMask (m, XI_ButtonPress);
14235 XISetMask (m, XI_ButtonRelease);
14236 XISetMask (m, XI_Motion);
14237 XISetMask (m, XI_Enter);
14238 XISetMask (m, XI_Leave);
14239
14240 XISelectEvents (XtDisplay (widget), XtWindow (widget),
14241 &mask, 1);
14242 }
14243#endif 14904#endif
14244#else /* !USE_MOTIF i.e. use Xaw */ 14905#else /* !USE_MOTIF i.e. use Xaw */
14245 14906
@@ -14661,24 +15322,8 @@ x_scroll_bar_create (struct window *w, int top, int left,
14661 /* Ask for input extension button and motion events. This lets us 15322 /* Ask for input extension button and motion events. This lets us
14662 send the proper `wheel-up' or `wheel-down' events to Emacs. */ 15323 send the proper `wheel-up' or `wheel-down' events to Emacs. */
14663 if (FRAME_DISPLAY_INFO (f)->supports_xi2) 15324 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
14664 { 15325 xi_select_scroll_bar_events (FRAME_DISPLAY_INFO (f),
14665 XIEventMask mask; 15326 window);
14666 ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
14667 unsigned char *m;
14668
14669 mask.mask = m = alloca (l);
14670 memset (m, 0, l);
14671 mask.mask_len = l;
14672
14673 mask.deviceid = XIAllMasterDevices;
14674 XISetMask (m, XI_ButtonPress);
14675 XISetMask (m, XI_ButtonRelease);
14676 XISetMask (m, XI_Motion);
14677 XISetMask (m, XI_Enter);
14678 XISetMask (m, XI_Leave);
14679
14680 XISelectEvents (FRAME_X_DISPLAY (f), window, &mask, 1);
14681 }
14682#endif 15327#endif
14683 15328
14684 bar->x_window = window; 15329 bar->x_window = window;
@@ -15563,17 +16208,17 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
15563 16208
15564 /* Get the mouse's position relative to the scroll bar window, and 16209 /* Get the mouse's position relative to the scroll bar window, and
15565 report that. */ 16210 report that. */
15566 if (XQueryPointer (FRAME_X_DISPLAY (f), w, 16211 if (x_query_pointer (FRAME_X_DISPLAY (f), w,
15567 16212
15568 /* Root, child, root x and root y. */ 16213 /* Root, child, root x and root y. */
15569 &dummy_window, &dummy_window, 16214 &dummy_window, &dummy_window,
15570 &dummy_coord, &dummy_coord, 16215 &dummy_coord, &dummy_coord,
15571 16216
15572 /* Position relative to scroll bar. */ 16217 /* Position relative to scroll bar. */
15573 &win_x, &win_y, 16218 &win_x, &win_y,
15574 16219
15575 /* Mouse buttons and modifier keys. */ 16220 /* Mouse buttons and modifier keys. */
15576 &dummy_mask)) 16221 &dummy_mask))
15577 { 16222 {
15578 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height); 16223 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
15579 16224
@@ -15632,17 +16277,17 @@ x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_windo
15632 16277
15633 /* Get the mouse's position relative to the scroll bar window, and 16278 /* Get the mouse's position relative to the scroll bar window, and
15634 report that. */ 16279 report that. */
15635 if (XQueryPointer (FRAME_X_DISPLAY (f), w, 16280 if (x_query_pointer (FRAME_X_DISPLAY (f), w,
15636 16281
15637 /* Root, child, root x and root y. */ 16282 /* Root, child, root x and root y. */
15638 &dummy_window, &dummy_window, 16283 &dummy_window, &dummy_window,
15639 &dummy_coord, &dummy_coord, 16284 &dummy_coord, &dummy_coord,
15640 16285
15641 /* Position relative to scroll bar. */ 16286 /* Position relative to scroll bar. */
15642 &win_x, &win_y, 16287 &win_x, &win_y,
15643 16288
15644 /* Mouse buttons and modifier keys. */ 16289 /* Mouse buttons and modifier keys. */
15645 &dummy_mask)) 16290 &dummy_mask))
15646 { 16291 {
15647 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width); 16292 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
15648 16293
@@ -16501,6 +17146,29 @@ x_wait_for_cell_change (Lisp_Object cell, struct timespec timeout)
16501 } 17146 }
16502} 17147}
16503 17148
17149/* Find whether or not an undelivered MONITORS_CHANGED_EVENT is
17150 already on the event queue. DPYINFO is the display any such event
17151 must apply to. */
17152
17153static bool
17154x_find_monitors_changed_event (struct x_display_info *dpyinfo)
17155{
17156 union buffered_input_event *event;
17157
17158 event = kbd_fetch_ptr;
17159
17160 while (event != kbd_store_ptr)
17161 {
17162 if (event->ie.kind == MONITORS_CHANGED_EVENT
17163 && XTERMINAL (event->ie.arg) == dpyinfo->terminal)
17164 return true;
17165
17166 event = X_NEXT_KBD_EVENT (event);
17167 }
17168
17169 return false;
17170}
17171
16504#ifdef USE_GTK 17172#ifdef USE_GTK
16505static void 17173static void
16506x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data) 17174x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data)
@@ -16518,6 +17186,9 @@ x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data)
16518 if (!dpyinfo) 17186 if (!dpyinfo)
16519 return; 17187 return;
16520 17188
17189 if (x_find_monitors_changed_event (dpyinfo))
17190 return;
17191
16521 XSETTERMINAL (terminal, dpyinfo->terminal); 17192 XSETTERMINAL (terminal, dpyinfo->terminal);
16522 17193
16523 current_monitors 17194 current_monitors
@@ -16645,6 +17316,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
16645 union buffered_input_event inev; 17316 union buffered_input_event inev;
16646 int count = 0; 17317 int count = 0;
16647 int do_help = 0; 17318 int do_help = 0;
17319#ifdef HAVE_XINPUT2
17320 struct xi_device_t *gen_help_device;
17321 Time gen_help_time;
17322#endif
16648 ptrdiff_t nbytes = 0; 17323 ptrdiff_t nbytes = 0;
16649 struct frame *any, *f = NULL; 17324 struct frame *any, *f = NULL;
16650 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight; 17325 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
@@ -16674,6 +17349,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
16674 EVENT_INIT (inev.ie); 17349 EVENT_INIT (inev.ie);
16675 inev.ie.kind = NO_EVENT; 17350 inev.ie.kind = NO_EVENT;
16676 inev.ie.arg = Qnil; 17351 inev.ie.arg = Qnil;
17352#ifdef HAVE_XINPUT2
17353 gen_help_device = NULL;
17354#endif
16677 17355
16678 /* Ignore events coming from various extensions, such as XFIXES and 17356 /* Ignore events coming from various extensions, such as XFIXES and
16679 XKB. */ 17357 XKB. */
@@ -17172,7 +17850,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
17172 goto done; 17850 goto done;
17173#endif 17851#endif
17174 17852
17175 xft_settings_event (dpyinfo, event); 17853 if (xft_settings_event (dpyinfo, event))
17854 goto done;
17176 17855
17177 f = any; 17856 f = any;
17178 /* We don't want to ever leak tooltip frames to Lisp code. */ 17857 /* We don't want to ever leak tooltip frames to Lisp code. */
@@ -17198,6 +17877,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
17198 if (!x_window_to_frame (dpyinfo, event->xselection.requestor)) 17877 if (!x_window_to_frame (dpyinfo, event->xselection.requestor))
17199 goto OTHER; 17878 goto OTHER;
17200#endif /* not USE_X_TOOLKIT and not USE_GTK */ 17879#endif /* not USE_X_TOOLKIT and not USE_GTK */
17880#ifdef HAVE_GTK3
17881 /* GTK 3 apparently chokes on these events since they have no
17882 associated device. (bug#56869, another bug as well that I
17883 can't find) */
17884 *finish = X_EVENT_DROP;
17885#endif
17201 x_handle_selection_notify (&event->xselection); 17886 x_handle_selection_notify (&event->xselection);
17202 break; 17887 break;
17203 17888
@@ -17206,6 +17891,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
17206 if (!x_window_to_frame (dpyinfo, event->xselectionclear.window)) 17891 if (!x_window_to_frame (dpyinfo, event->xselectionclear.window))
17207 goto OTHER; 17892 goto OTHER;
17208#endif /* not USE_X_TOOLKIT and not USE_GTK */ 17893#endif /* not USE_X_TOOLKIT and not USE_GTK */
17894#ifdef HAVE_GTK3
17895 *finish = X_EVENT_DROP;
17896#endif
17209 { 17897 {
17210 const XSelectionClearEvent *eventp = &event->xselectionclear; 17898 const XSelectionClearEvent *eventp = &event->xselectionclear;
17211 17899
@@ -17232,6 +17920,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
17232 if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner)) 17920 if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner))
17233 goto OTHER; 17921 goto OTHER;
17234#endif /* USE_X_TOOLKIT */ 17922#endif /* USE_X_TOOLKIT */
17923#ifdef HAVE_GTK3
17924 *finish = X_EVENT_DROP;
17925#endif
17235 { 17926 {
17236 const XSelectionRequestEvent *eventp = &event->xselectionrequest; 17927 const XSelectionRequestEvent *eventp = &event->xselectionrequest;
17237 17928
@@ -17873,6 +18564,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
17873 x_display_set_last_user_time (dpyinfo, event->xkey.time, 18564 x_display_set_last_user_time (dpyinfo, event->xkey.time,
17874 event->xkey.send_event); 18565 event->xkey.send_event);
17875 ignore_next_mouse_click_timeout = 0; 18566 ignore_next_mouse_click_timeout = 0;
18567
17876 coding = Qlatin_1; 18568 coding = Qlatin_1;
17877 18569
17878#if defined (USE_X_TOOLKIT) || defined (USE_GTK) 18570#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
@@ -17883,6 +18575,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
17883 18575
17884 f = any; 18576 f = any;
17885 18577
18578#ifdef USE_GTK
18579 if (f)
18580 x_set_gtk_user_time (f, event->xkey.time);
18581#endif
18582
17886 /* If mouse-highlight is an integer, input clears out 18583 /* If mouse-highlight is an integer, input clears out
17887 mouse highlighting. */ 18584 mouse highlighting. */
17888 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight) 18585 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
@@ -18462,7 +19159,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
18462 { 19159 {
18463 /* Now clear dpyinfo->last_mouse_motion_frame, or 19160 /* Now clear dpyinfo->last_mouse_motion_frame, or
18464 gui_redo_mouse_highlight will end up highlighting the 19161 gui_redo_mouse_highlight will end up highlighting the
18465 last known poisition of the mouse if a tooltip frame is 19162 last known position of the mouse if a tooltip frame is
18466 later unmapped. */ 19163 later unmapped. */
18467 19164
18468 if (f == dpyinfo->last_mouse_motion_frame) 19165 if (f == dpyinfo->last_mouse_motion_frame)
@@ -18885,13 +19582,20 @@ handle_one_xevent (struct x_display_info *dpyinfo,
18885 if (configureEvent.xconfigure.width != dpyinfo->screen_width 19582 if (configureEvent.xconfigure.width != dpyinfo->screen_width
18886 || configureEvent.xconfigure.height != dpyinfo->screen_height) 19583 || configureEvent.xconfigure.height != dpyinfo->screen_height)
18887 { 19584 {
18888 inev.ie.kind = MONITORS_CHANGED_EVENT; 19585 /* Also avoid storing duplicate events here, since
18889 XSETTERMINAL (inev.ie.arg, dpyinfo->terminal); 19586 Fx_display_monitor_attributes_list will return the
19587 same information for both invocations of the
19588 hook. */
19589 if (!x_find_monitors_changed_event (dpyinfo))
19590 {
19591 inev.ie.kind = MONITORS_CHANGED_EVENT;
19592 XSETTERMINAL (inev.ie.arg, dpyinfo->terminal);
18890 19593
18891 /* Store this event now since inev.ie.type could be set to 19594 /* Store this event now since inev.ie.type could be set to
18892 MOVE_FRAME_EVENT later. */ 19595 MOVE_FRAME_EVENT later. */
18893 kbd_buffer_store_event (&inev.ie); 19596 kbd_buffer_store_event (&inev.ie);
18894 inev.ie.kind = NO_EVENT; 19597 inev.ie.kind = NO_EVENT;
19598 }
18895 19599
18896 /* Also update the position of the drag-and-drop 19600 /* Also update the position of the drag-and-drop
18897 tooltip. */ 19601 tooltip. */
@@ -19663,11 +20367,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19663 { 20367 {
19664 case XI_FocusIn: 20368 case XI_FocusIn:
19665 { 20369 {
19666 XIFocusInEvent *focusin = (XIFocusInEvent *) xi_event; 20370 XIFocusInEvent *focusin;
19667 struct xi_device_t *source;
19668 20371
20372 focusin = (XIFocusInEvent *) xi_event;
19669 any = x_any_window_to_frame (dpyinfo, focusin->event); 20373 any = x_any_window_to_frame (dpyinfo, focusin->event);
19670 source = xi_device_from_id (dpyinfo, focusin->sourceid); 20374
19671#ifdef USE_GTK 20375#ifdef USE_GTK
19672 /* Some WMs (e.g. Mutter in Gnome Shell), don't unmap 20376 /* Some WMs (e.g. Mutter in Gnome Shell), don't unmap
19673 minimized/iconified windows; thus, for those WMs we won't get 20377 minimized/iconified windows; thus, for those WMs we won't get
@@ -19696,24 +20400,19 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19696 } 20400 }
19697 } 20401 }
19698 20402
19699 x_detect_focus_change (dpyinfo, any, event, &inev.ie); 20403 xi_focus_handle_for_device (dpyinfo, any, xi_event);
19700 20404
19701 if (inev.ie.kind != NO_EVENT && source)
19702 inev.ie.device = source->name;
19703 goto XI_OTHER; 20405 goto XI_OTHER;
19704 } 20406 }
19705 20407
19706 case XI_FocusOut: 20408 case XI_FocusOut:
19707 { 20409 {
19708 XIFocusOutEvent *focusout = (XIFocusOutEvent *) xi_event; 20410 XIFocusOutEvent *focusout;
19709 struct xi_device_t *source;
19710 20411
20412 focusout = (XIFocusOutEvent *) xi_event;
19711 any = x_any_window_to_frame (dpyinfo, focusout->event); 20413 any = x_any_window_to_frame (dpyinfo, focusout->event);
19712 source = xi_device_from_id (dpyinfo, focusout->sourceid); 20414 xi_focus_handle_for_device (dpyinfo, any, xi_event);
19713 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
19714 20415
19715 if (inev.ie.kind != NO_EVENT && source)
19716 inev.ie.device = source->name;
19717 goto XI_OTHER; 20416 goto XI_OTHER;
19718 } 20417 }
19719 20418
@@ -19762,7 +20461,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19762 are an inferiors of the frame's top window, which will 20461 are an inferiors of the frame's top window, which will
19763 get virtual events. */ 20462 get virtual events. */
19764 if (any) 20463 if (any)
19765 x_detect_focus_change (dpyinfo, any, event, &inev.ie); 20464 xi_focus_handle_for_device (dpyinfo, any, xi_event);
19766 20465
19767 if (!any) 20466 if (!any)
19768 any = x_any_window_to_frame (dpyinfo, enter->event); 20467 any = x_any_window_to_frame (dpyinfo, enter->event);
@@ -19902,7 +20601,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19902#endif 20601#endif
19903 20602
19904 if (any) 20603 if (any)
19905 x_detect_focus_change (dpyinfo, any, event, &inev.ie); 20604 xi_focus_handle_for_device (dpyinfo, any, xi_event);
19906 20605
19907#ifndef USE_X_TOOLKIT 20606#ifndef USE_X_TOOLKIT
19908 f = x_top_window_to_frame (dpyinfo, leave->event); 20607 f = x_top_window_to_frame (dpyinfo, leave->event);
@@ -19929,7 +20628,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19929 { 20628 {
19930 /* Now clear dpyinfo->last_mouse_motion_frame, or 20629 /* Now clear dpyinfo->last_mouse_motion_frame, or
19931 gui_redo_mouse_highlight will end up highlighting 20630 gui_redo_mouse_highlight will end up highlighting
19932 the last known poisition of the mouse if a 20631 the last known position of the mouse if a
19933 tooltip frame is later unmapped. */ 20632 tooltip frame is later unmapped. */
19934 20633
19935 if (f == dpyinfo->last_mouse_motion_frame) 20634 if (f == dpyinfo->last_mouse_motion_frame)
@@ -20590,7 +21289,15 @@ handle_one_xevent (struct x_display_info *dpyinfo,
20590 has changed, generate a HELP_EVENT. */ 21289 has changed, generate a HELP_EVENT. */
20591 if (!NILP (help_echo_string) 21290 if (!NILP (help_echo_string)
20592 || !NILP (previous_help_echo_string)) 21291 || !NILP (previous_help_echo_string))
20593 do_help = 1; 21292 {
21293 /* Also allow the focus and client pointer to be
21294 adjusted accordingly, in case a help tooltip is
21295 shown. */
21296 gen_help_device = device;
21297 gen_help_time = xev->time;
21298
21299 do_help = 1;
21300 }
20594 goto XI_OTHER; 21301 goto XI_OTHER;
20595 } 21302 }
20596 21303
@@ -20653,6 +21360,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
20653 } 21360 }
20654#endif 21361#endif
20655 21362
21363 if (f && device)
21364 xi_handle_interaction (dpyinfo, f, device,
21365 xev->time);
21366
20656 if (xev->evtype == XI_ButtonPress 21367 if (xev->evtype == XI_ButtonPress
20657 && x_dnd_last_seen_window != None) 21368 && x_dnd_last_seen_window != None)
20658 { 21369 {
@@ -20899,11 +21610,19 @@ handle_one_xevent (struct x_display_info *dpyinfo,
20899 xev->send_event); 21610 xev->send_event);
20900 21611
20901 source = xi_device_from_id (dpyinfo, xev->sourceid); 21612 source = xi_device_from_id (dpyinfo, xev->sourceid);
21613 device = xi_device_from_id (dpyinfo, xev->deviceid);
20902 21614
20903#ifdef HAVE_XWIDGETS 21615#ifdef HAVE_XWIDGETS
20904 xvw = xwidget_view_from_window (xev->event); 21616 xvw = xwidget_view_from_window (xev->event);
20905 if (xvw) 21617 if (xvw)
20906 { 21618 {
21619 /* If the user interacts with a frame that's focused
21620 on another device, but not the current focus
21621 frame, make it the focus frame. */
21622 if (device)
21623 xi_handle_interaction (dpyinfo, xvw->frame,
21624 device, xev->time);
21625
20907 xwidget_button (xvw, xev->evtype == XI_ButtonPress, 21626 xwidget_button (xvw, xev->evtype == XI_ButtonPress,
20908 lrint (xev->event_x), lrint (xev->event_y), 21627 lrint (xev->event_x), lrint (xev->event_y),
20909 xev->detail, xi_convert_event_state (xev), 21628 xev->detail, xi_convert_event_state (xev),
@@ -20923,8 +21642,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
20923 } 21642 }
20924#endif 21643#endif
20925 21644
20926 device = xi_device_from_id (dpyinfo, xev->deviceid);
20927
20928 if (!device) 21645 if (!device)
20929 goto XI_OTHER; 21646 goto XI_OTHER;
20930 21647
@@ -20962,6 +21679,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
20962 } 21679 }
20963 } 21680 }
20964 21681
21682 if (f)
21683 {
21684 /* If the user interacts with a frame that's focused
21685 on another device, but not the current focus
21686 frame, make it the focus frame. */
21687 if (device)
21688 xi_handle_interaction (dpyinfo, f, device,
21689 xev->time);
21690 }
21691
20965#ifdef USE_GTK 21692#ifdef USE_GTK
20966 if (!f) 21693 if (!f)
20967 { 21694 {
@@ -21243,6 +21970,25 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21243 21970
21244 f = x_any_window_to_frame (dpyinfo, xev->event); 21971 f = x_any_window_to_frame (dpyinfo, xev->event);
21245 21972
21973 /* GTK handles TAB events in an undesirable manner, so
21974 keyboard events are always dropped. But as a side
21975 effect, the user time will no longer be set by GDK,
21976 so do that manually. */
21977#ifdef USE_GTK
21978 if (f)
21979 x_set_gtk_user_time (f, xev->time);
21980#endif
21981
21982 if (f)
21983 {
21984 /* If the user interacts with a frame that's focused
21985 on another device, but not the current focus
21986 frame, make it the focus frame. */
21987 if (device)
21988 xi_handle_interaction (dpyinfo, f, device,
21989 xev->time);
21990 }
21991
21246 XKeyPressedEvent xkey; 21992 XKeyPressedEvent xkey;
21247 21993
21248 memset (&xkey, 0, sizeof xkey); 21994 memset (&xkey, 0, sizeof xkey);
@@ -21717,14 +22463,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21717 22463
21718 case XI_HierarchyChanged: 22464 case XI_HierarchyChanged:
21719 { 22465 {
21720 XIHierarchyEvent *hev = (XIHierarchyEvent *) xi_event; 22466 XIHierarchyEvent *hev;
21721 XIDeviceInfo *info; 22467 XIDeviceInfo *info;
21722 int i, j, ndevices, n_disabled, *disabled; 22468 int i, ndevices, n_disabled, *disabled;
21723 struct xi_device_t *device, *devices; 22469 struct xi_device_t *device;
21724#ifdef HAVE_XINPUT2_2 22470 bool any_changed;
21725 struct xi_touch_point_t *tem, *last;
21726#endif
21727 22471
22472 any_changed = false;
22473 hev = (XIHierarchyEvent *) xi_event;
21728 disabled = SAFE_ALLOCA (sizeof *disabled * hev->num_info); 22474 disabled = SAFE_ALLOCA (sizeof *disabled * hev->num_info);
21729 n_disabled = 0; 22475 n_disabled = 0;
21730 22476
@@ -21734,44 +22480,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21734 { 22480 {
21735 /* Handle all disabled devices now, to prevent 22481 /* Handle all disabled devices now, to prevent
21736 things happening out-of-order later. */ 22482 things happening out-of-order later. */
21737 if (n_disabled)
21738 {
21739 ndevices = 0;
21740 devices = xmalloc (sizeof *devices * dpyinfo->num_devices);
21741
21742 for (i = 0; i < dpyinfo->num_devices; ++i)
21743 {
21744 for (j = 0; j < n_disabled; ++j)
21745 {
21746 if (disabled[j] == dpyinfo->devices[i].device_id)
21747 {
21748#ifdef HAVE_XINPUT2_1
21749 xfree (dpyinfo->devices[i].valuators);
21750#endif
21751#ifdef HAVE_XINPUT2_2
21752 tem = dpyinfo->devices[i].touchpoints;
21753 while (tem)
21754 {
21755 last = tem;
21756 tem = tem->next;
21757 xfree (last);
21758 }
21759#endif
21760 goto continue_detachment;
21761 }
21762 }
21763
21764 devices[ndevices++] = dpyinfo->devices[i];
21765
21766 continue_detachment:
21767 continue;
21768 }
21769
21770 xfree (dpyinfo->devices);
21771 dpyinfo->devices = devices;
21772 dpyinfo->num_devices = ndevices;
21773 22483
22484 if (ndevices)
22485 {
22486 xi_disable_devices (dpyinfo, disabled, n_disabled);
21774 n_disabled = 0; 22487 n_disabled = 0;
22488
22489 /* This flag really just means that disabled
22490 devices were handled early and should be
22491 used in conjunction with n_disabled. */
22492 any_changed = true;
21775 } 22493 }
21776 22494
21777 x_catch_errors (dpyinfo->display); 22495 x_catch_errors (dpyinfo->display);
@@ -21784,6 +22502,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21784 dpyinfo->devices 22502 dpyinfo->devices
21785 = xrealloc (dpyinfo->devices, (sizeof *dpyinfo->devices 22503 = xrealloc (dpyinfo->devices, (sizeof *dpyinfo->devices
21786 * ++dpyinfo->num_devices)); 22504 * ++dpyinfo->num_devices));
22505 memset (dpyinfo->devices + dpyinfo->num_devices - 1,
22506 0, sizeof *dpyinfo->devices);
21787 device = &dpyinfo->devices[dpyinfo->num_devices - 1]; 22507 device = &dpyinfo->devices[dpyinfo->num_devices - 1];
21788 xi_populate_device_from_info (device, info); 22508 xi_populate_device_from_info (device, info);
21789 } 22509 }
@@ -21805,7 +22525,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21805 if (info) 22525 if (info)
21806 { 22526 {
21807 if (device && info->enabled) 22527 if (device && info->enabled)
21808 device->use = info->use; 22528 {
22529 device->use = info->use;
22530 device->attachment = info->attachment;
22531 }
21809 else if (device) 22532 else if (device)
21810 disabled[n_disabled++] = hev->info[i].deviceid; 22533 disabled[n_disabled++] = hev->info[i].deviceid;
21811 22534
@@ -21814,174 +22537,37 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21814 } 22537 }
21815 } 22538 }
21816 22539
21817 if (n_disabled) 22540 /* Delete all devices that were disabled by this
21818 { 22541 event. */
21819 ndevices = 0; 22542 xi_disable_devices (dpyinfo, disabled, n_disabled);
21820 devices = xmalloc (sizeof *devices * dpyinfo->num_devices);
21821
21822 for (i = 0; i < dpyinfo->num_devices; ++i)
21823 {
21824 for (j = 0; j < n_disabled; ++j)
21825 {
21826 if (disabled[j] == dpyinfo->devices[i].device_id)
21827 {
21828#ifdef HAVE_XINPUT2_1
21829 xfree (dpyinfo->devices[i].valuators);
21830#endif
21831#ifdef HAVE_XINPUT2_2
21832 tem = dpyinfo->devices[i].touchpoints;
21833 while (tem)
21834 {
21835 last = tem;
21836 tem = tem->next;
21837 xfree (last);
21838 }
21839#endif
21840 goto break_detachment;
21841 }
21842 }
21843
21844 devices[ndevices++] = dpyinfo->devices[i];
21845
21846 break_detachment:
21847 continue;
21848 }
21849 22543
21850 xfree (dpyinfo->devices); 22544 /* If the device hierarchy has been changed, recompute
21851 dpyinfo->devices = devices; 22545 focus. This might seem like a micro-optimization but
21852 dpyinfo->num_devices = ndevices; 22546 it actually keeps the focus from changing in some
21853 } 22547 cases where it would be undesierable. */
22548 if (any_changed || n_disabled)
22549 xi_handle_focus_change (dpyinfo);
21854 22550
21855 goto XI_OTHER; 22551 goto XI_OTHER;
21856 } 22552 }
21857 22553
21858 case XI_DeviceChanged: 22554 case XI_DeviceChanged:
21859 { 22555 {
21860 XIDeviceChangedEvent *device_changed = (XIDeviceChangedEvent *) xi_event; 22556 XIDeviceChangedEvent *device_changed;
21861 struct xi_device_t *device; 22557 struct xi_device_t *device;
21862#ifdef HAVE_XINPUT2_2
21863 struct xi_touch_point_t *tem, *last;
21864#endif
21865 int c;
21866#ifdef HAVE_XINPUT2_1
21867 int i;
21868#endif
21869 22558
22559 device_changed = (XIDeviceChangedEvent *) xi_event;
21870 device = xi_device_from_id (dpyinfo, device_changed->deviceid); 22560 device = xi_device_from_id (dpyinfo, device_changed->deviceid);
21871 22561
21872 if (!device) 22562 /* If the device isn't enabled, then stop handling this
21873 { 22563 event. A HierarchyChanged event will be sent if it
21874 /* An existing device might have been enabled. */ 22564 is enabled afterwards. */
21875 x_cache_xi_devices (dpyinfo);
21876
21877 /* Now try to find the device again, in case it was
21878 just enabled. */
21879 device = xi_device_from_id (dpyinfo, device_changed->deviceid);
21880 }
21881
21882 /* If it wasn't enabled, then stop handling this event. */
21883 if (!device) 22565 if (!device)
21884 goto XI_OTHER; 22566 goto XI_OTHER;
21885 22567
21886 /* Free data that we will regenerate from new 22568 /* Now handle the event by retrieving scroll valuators
21887 information. */ 22569 and touch info. */
21888#ifdef HAVE_XINPUT2_1 22570 xi_handle_device_changed (dpyinfo, device, device_changed);
21889 device->valuators = xrealloc (device->valuators,
21890 (device_changed->num_classes
21891 * sizeof *device->valuators));
21892 device->scroll_valuator_count = 0;
21893#endif
21894#ifdef HAVE_XINPUT2_2
21895 device->direct_p = false;
21896#endif
21897
21898 for (c = 0; c < device_changed->num_classes; ++c)
21899 {
21900 switch (device_changed->classes[c]->type)
21901 {
21902#ifdef HAVE_XINPUT2_1
21903 case XIScrollClass:
21904 {
21905 XIScrollClassInfo *info;
21906
21907 info = (XIScrollClassInfo *) device_changed->classes[c];
21908 struct xi_scroll_valuator_t *valuator;
21909
21910 valuator = &device->valuators[device->scroll_valuator_count++];
21911 valuator->horizontal
21912 = (info->scroll_type == XIScrollTypeHorizontal);
21913 valuator->invalid_p = true;
21914 valuator->emacs_value = DBL_MIN;
21915 valuator->increment = info->increment;
21916 valuator->number = info->number;
21917
21918 break;
21919 }
21920#endif
21921
21922#ifdef HAVE_XINPUT2_2
21923 case XITouchClass:
21924 {
21925 XITouchClassInfo *info;
21926
21927 info = (XITouchClassInfo *) device_changed->classes[c];
21928 device->direct_p = info->mode == XIDirectTouch;
21929 }
21930#endif
21931 default:
21932 break;
21933 }
21934 }
21935
21936#ifdef HAVE_XINPUT2_1
21937 for (c = 0; c < device_changed->num_classes; ++c)
21938 {
21939 if (device_changed->classes[c]->type == XIValuatorClass)
21940 {
21941 XIValuatorClassInfo *info;
21942
21943 info = (XIValuatorClassInfo *) device_changed->classes[c];
21944
21945 for (i = 0; i < device->scroll_valuator_count; ++i)
21946 {
21947 if (device->valuators[i].number == info->number)
21948 {
21949 device->valuators[i].invalid_p = false;
21950 device->valuators[i].current_value = info->value;
21951
21952 /* Make sure that this is reset if the
21953 pointer moves into a window of ours.
21954
21955 Otherwise the valuator state could be
21956 left invalid if the DeviceChange
21957 event happened with the pointer
21958 outside any Emacs frame. */
21959 device->valuators[i].pending_enter_reset = true;
21960 }
21961 }
21962 }
21963 }
21964#endif
21965
21966#ifdef HAVE_XINPUT2_2
21967 /* The device is no longer a DirectTouch device, so
21968 remove any touchpoints that we might have
21969 recorded. */
21970 if (!device->direct_p)
21971 {
21972 tem = device->touchpoints;
21973
21974 while (tem)
21975 {
21976 last = tem;
21977 tem = tem->next;
21978 xfree (last);
21979 }
21980
21981 device->touchpoints = NULL;
21982 }
21983#endif
21984
21985 goto XI_OTHER; 22571 goto XI_OTHER;
21986 } 22572 }
21987 22573
@@ -22533,7 +23119,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
22533 || event->type == (dpyinfo->xrandr_event_base 23119 || event->type == (dpyinfo->xrandr_event_base
22534 + RRNotify))) 23120 + RRNotify)))
22535 { 23121 {
22536 union buffered_input_event *ev;
22537 Time timestamp; 23122 Time timestamp;
22538 Lisp_Object current_monitors; 23123 Lisp_Object current_monitors;
22539 XRRScreenChangeNotifyEvent *notify; 23124 XRRScreenChangeNotifyEvent *notify;
@@ -22561,13 +23146,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
22561 else 23146 else
22562 timestamp = 0; 23147 timestamp = 0;
22563 23148
22564 ev = (kbd_store_ptr == kbd_buffer 23149 if (x_find_monitors_changed_event (dpyinfo))
22565 ? kbd_buffer + KBD_BUFFER_SIZE - 1
22566 : kbd_store_ptr - 1);
22567
22568 if (kbd_store_ptr != kbd_fetch_ptr
22569 && ev->ie.kind == MONITORS_CHANGED_EVENT
22570 && XTERMINAL (ev->ie.arg) == dpyinfo->terminal)
22571 /* Don't store a MONITORS_CHANGED_EVENT if there is 23150 /* Don't store a MONITORS_CHANGED_EVENT if there is
22572 already an undelivered event on the queue. */ 23151 already an undelivered event on the queue. */
22573 goto OTHER; 23152 goto OTHER;
@@ -22655,6 +23234,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
22655 if (do_help > 0) 23234 if (do_help > 0)
22656 { 23235 {
22657 any_help_event_p = true; 23236 any_help_event_p = true;
23237#ifdef HAVE_XINPUT2
23238 if (gen_help_device)
23239 xi_handle_interaction (dpyinfo, f,
23240 gen_help_device,
23241 gen_help_time);
23242#endif
22658 gen_help_event (help_echo_string, frame, help_echo_window, 23243 gen_help_event (help_echo_string, frame, help_echo_window,
22659 help_echo_object, help_echo_pos); 23244 help_echo_object, help_echo_pos);
22660 } 23245 }
@@ -23132,8 +23717,6 @@ x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
23132 xic_set_preeditarea (w, x, y); 23717 xic_set_preeditarea (w, x, y);
23133#endif 23718#endif
23134 } 23719 }
23135
23136 XFlush (FRAME_X_DISPLAY (f));
23137} 23720}
23138 23721
23139 23722
@@ -25648,6 +26231,7 @@ x_make_frame_visible (struct frame *f)
25648 struct x_display_info *dpyinfo; 26231 struct x_display_info *dpyinfo;
25649 struct x_output *output; 26232 struct x_output *output;
25650#endif 26233#endif
26234 bool output_flushed;
25651 26235
25652 if (FRAME_PARENT_FRAME (f)) 26236 if (FRAME_PARENT_FRAME (f))
25653 { 26237 {
@@ -25738,8 +26322,6 @@ x_make_frame_visible (struct frame *f)
25738 } 26322 }
25739 } 26323 }
25740 26324
25741 XFlush (FRAME_X_DISPLAY (f));
25742
25743 /* Synchronize to ensure Emacs knows the frame is visible 26325 /* Synchronize to ensure Emacs knows the frame is visible
25744 before we do anything else. We do this loop with input not blocked 26326 before we do anything else. We do this loop with input not blocked
25745 so that incoming events are handled. */ 26327 so that incoming events are handled. */
@@ -25758,6 +26340,10 @@ x_make_frame_visible (struct frame *f)
25758 /* This must come after we set COUNT. */ 26340 /* This must come after we set COUNT. */
25759 unblock_input (); 26341 unblock_input ();
25760 26342
26343 /* Keep track of whether or not the output buffer was flushed, to
26344 avoid any extra flushes. */
26345 output_flushed = false;
26346
25761 /* We unblock here so that arriving X events are processed. */ 26347 /* We unblock here so that arriving X events are processed. */
25762 26348
25763 /* Now move the window back to where it was "supposed to be". 26349 /* Now move the window back to where it was "supposed to be".
@@ -25791,6 +26377,7 @@ x_make_frame_visible (struct frame *f)
25791 there, and take the potential window manager hit. */ 26377 there, and take the potential window manager hit. */
25792 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 26378 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
25793 &rootw, &x, &y, &width, &height, &border, &depth); 26379 &rootw, &x, &y, &width, &height, &border, &depth);
26380 output_flushed = true;
25794 26381
25795 if (original_left != x || original_top != y) 26382 if (original_left != x || original_top != y)
25796 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 26383 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
@@ -25825,7 +26412,11 @@ x_make_frame_visible (struct frame *f)
25825 (f, build_string ("x_make_frame_visible")); 26412 (f, build_string ("x_make_frame_visible"));
25826 26413
25827 x_wait_for_event (f, MapNotify); 26414 x_wait_for_event (f, MapNotify);
26415 output_flushed = true;
25828 } 26416 }
26417
26418 if (!output_flushed)
26419 x_flush (f);
25829 } 26420 }
25830} 26421}
25831 26422
@@ -26045,6 +26636,11 @@ x_free_frame_resources (struct frame *f)
26045 26636
26046 block_input (); 26637 block_input ();
26047 26638
26639#ifdef HAVE_XINPUT2
26640 /* Remove any record of this frame being focused. */
26641 xi_handle_delete_frame (dpyinfo, f);
26642#endif
26643
26048 /* If a display connection is dead, don't try sending more 26644 /* If a display connection is dead, don't try sending more
26049 commands to the X server. */ 26645 commands to the X server. */
26050 if (dpyinfo->display) 26646 if (dpyinfo->display)
@@ -26192,7 +26788,10 @@ x_free_frame_resources (struct frame *f)
26192 if (f->output_data.x->bottom_left_corner_cursor != 0) 26788 if (f->output_data.x->bottom_left_corner_cursor != 0)
26193 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_left_corner_cursor); 26789 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_left_corner_cursor);
26194 26790
26195 XFlush (FRAME_X_DISPLAY (f)); 26791 /* Free sync fences. */
26792#if defined HAVE_XSYNCTRIGGERFENCE && !defined USE_GTK
26793 x_sync_free_fences (f);
26794#endif
26196 } 26795 }
26197 26796
26198#ifdef HAVE_GTK3 26797#ifdef HAVE_GTK3
@@ -27416,6 +28015,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
27416 int minor = 0; 28015 int minor = 0;
27417#endif 28016#endif
27418 28017
28018 dpyinfo->client_pointer_device = -1;
28019
27419 if (XQueryExtension (dpyinfo->display, "XInputExtension", 28020 if (XQueryExtension (dpyinfo->display, "XInputExtension",
27420 &dpyinfo->xi2_opcode, &xi_first_event, 28021 &dpyinfo->xi2_opcode, &xi_first_event,
27421 &xi_first_error)) 28022 &xi_first_error))
diff --git a/src/xterm.h b/src/xterm.h
index 2b8a2e5da49..e97f3d4c831 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -238,23 +238,54 @@ struct xi_touch_point_t
238 238
239struct xi_device_t 239struct xi_device_t
240{ 240{
241 /* The numerical ID of this device. */
241 int device_id; 242 int device_id;
243
242#ifdef HAVE_XINPUT2_1 244#ifdef HAVE_XINPUT2_1
245 /* The number of scroll valuators in `valuators'. */
243 int scroll_valuator_count; 246 int scroll_valuator_count;
244#endif 247#endif
248
249 /* Whether or not the device is grabbed and its use. */
245 int grab, use; 250 int grab, use;
251
252 /* The attached device. Only valid if USE is some kind of master
253 device. */
254 int attachment;
255
246#ifdef HAVE_XINPUT2_2 256#ifdef HAVE_XINPUT2_2
257 /* Whether or not this device is a direct touch device. */
247 bool direct_p; 258 bool direct_p;
248#endif 259#endif
249 260
250#ifdef HAVE_XINPUT2_1 261#ifdef HAVE_XINPUT2_1
262 /* An array of scroll valuators Emacs knows about. */
251 struct xi_scroll_valuator_t *valuators; 263 struct xi_scroll_valuator_t *valuators;
252#endif 264#endif
265
253#ifdef HAVE_XINPUT2_2 266#ifdef HAVE_XINPUT2_2
267 /* An array of in-progress touchscreen events. */
254 struct xi_touch_point_t *touchpoints; 268 struct xi_touch_point_t *touchpoints;
255#endif 269#endif
256 270
271 /* The name of this device. */
257 Lisp_Object name; 272 Lisp_Object name;
273
274 /* The time at which `focus_frame' became the keyboard focus (only
275 applies to master devices). */
276 Time focus_frame_time;
277
278 /* The frame that is currently this device's keyboard focus, or
279 NULL. */
280 struct frame *focus_frame;
281
282 /* The time at which `focus_frame' became the implicit keyboard
283 focus. */
284 Time focus_implicit_time;
285
286 /* The frame that is currently this device's implicit keyboard
287 focus, or NULL. */
288 struct frame *focus_implicit_frame;
258}; 289};
259#endif 290#endif
260 291
@@ -482,7 +513,10 @@ struct x_display_info
482 /* The last frame mentioned in a FocusIn or FocusOut event. This is 513 /* The last frame mentioned in a FocusIn or FocusOut event. This is
483 separate from x_focus_frame, because whether or not LeaveNotify 514 separate from x_focus_frame, because whether or not LeaveNotify
484 events cause us to lose focus depends on whether or not we have 515 events cause us to lose focus depends on whether or not we have
485 received a FocusIn event for it. */ 516 received a FocusIn event for it.
517
518 This field is not used when the input extension is being
519 utilized. */
486 struct frame *x_focus_event_frame; 520 struct frame *x_focus_event_frame;
487 521
488 /* The frame which currently has the visual highlight, and should get 522 /* The frame which currently has the visual highlight, and should get
@@ -614,9 +648,9 @@ struct x_display_info
614 Xatom_net_wm_state_shaded, Xatom_net_frame_extents, Xatom_net_current_desktop, 648 Xatom_net_wm_state_shaded, Xatom_net_frame_extents, Xatom_net_current_desktop,
615 Xatom_net_workarea, Xatom_net_wm_opaque_region, Xatom_net_wm_ping, 649 Xatom_net_workarea, Xatom_net_wm_opaque_region, Xatom_net_wm_ping,
616 Xatom_net_wm_sync_request, Xatom_net_wm_sync_request_counter, 650 Xatom_net_wm_sync_request, Xatom_net_wm_sync_request_counter,
617 Xatom_net_wm_frame_drawn, Xatom_net_wm_frame_timings, Xatom_net_wm_user_time, 651 Xatom_net_wm_sync_fences, Xatom_net_wm_frame_drawn, Xatom_net_wm_frame_timings,
618 Xatom_net_wm_user_time_window, Xatom_net_client_list_stacking, 652 Xatom_net_wm_user_time, Xatom_net_wm_user_time_window,
619 Xatom_net_wm_pid; 653 Xatom_net_client_list_stacking, Xatom_net_wm_pid;
620 654
621 /* XSettings atoms and windows. */ 655 /* XSettings atoms and windows. */
622 Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr; 656 Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr;
@@ -678,13 +712,27 @@ struct x_display_info
678 712
679#ifdef HAVE_XINPUT2 713#ifdef HAVE_XINPUT2
680 bool supports_xi2; 714 bool supports_xi2;
715
716 /* The minor version of the input extension. (Major is always
717 2.x.) */
681 int xi2_version; 718 int xi2_version;
719
720 /* The generic event opcode of XI2 events. */
682 int xi2_opcode; 721 int xi2_opcode;
683 722
723 /* The number of devices on this display known to Emacs. */
684 int num_devices; 724 int num_devices;
725
726 /* Array of all input extension devices on this display known to
727 Emacs. */
685 struct xi_device_t *devices; 728 struct xi_device_t *devices;
686 729
730 /* Pending keystroke time. */
687 Time pending_keystroke_time; 731 Time pending_keystroke_time;
732
733 /* Pending keystroke source. If a core KeyPress event arrives with
734 the same timestamp as pending_keystroke_time, it will be treated
735 as originating from this device. */
688 int pending_keystroke_source; 736 int pending_keystroke_source;
689 737
690#if defined USE_GTK && !defined HAVE_GTK3 738#if defined USE_GTK && !defined HAVE_GTK3
@@ -694,6 +742,10 @@ struct x_display_info
694 input method) core key event. */ 742 input method) core key event. */
695 bool pending_keystroke_time_special_p; 743 bool pending_keystroke_time_special_p;
696#endif 744#endif
745
746 /* The client pointer. We keep a record client-side to avoid
747 calling XISetClientPointer all the time. */
748 int client_pointer_device;
697#endif 749#endif
698 750
699#ifdef HAVE_XKB 751#ifdef HAVE_XKB
@@ -769,6 +821,16 @@ struct x_display_info
769 /* The pending drag-and-drop time for middle-click based 821 /* The pending drag-and-drop time for middle-click based
770 drag-and-drop emulation. */ 822 drag-and-drop emulation. */
771 Time pending_dnd_time; 823 Time pending_dnd_time;
824
825#if defined HAVE_XSYNC && !defined USE_GTK
826 /* Whether or not the server time is probably the same as
827 "clock_gettime (CLOCK_MONOTONIC, ...)". */
828 bool server_time_monotonic_p;
829
830 /* The time difference between the X server clock and the monotonic
831 clock. */
832 int64_t server_time_offset;
833#endif
772}; 834};
773 835
774#ifdef HAVE_X_I18N 836#ifdef HAVE_X_I18N
@@ -1061,6 +1123,19 @@ struct x_output
1061 /* Whether or not Emacs should wait for the compositing manager to 1123 /* Whether or not Emacs should wait for the compositing manager to
1062 draw frames before starting a new frame. */ 1124 draw frames before starting a new frame. */
1063 bool_bf use_vsync_p : 1; 1125 bool_bf use_vsync_p : 1;
1126
1127 /* The time (in microseconds) it took to draw the last frame. */
1128 uint64_t last_frame_time;
1129
1130 /* A temporary time used to calculate that value. */
1131 uint64_t temp_frame_time;
1132
1133#ifdef HAVE_XSYNCTRIGGERFENCE
1134 /* An array of two sync fences that are triggered in order after a
1135 frame completes. Not initialized if the XSync extension is too
1136 old to support sync fences. */
1137 XSyncFence sync_fences[2];
1138#endif
1064#endif 1139#endif
1065#endif 1140#endif
1066 1141
@@ -1078,7 +1153,9 @@ struct x_output
1078 1153
1079 /* Keep track of focus. May be EXPLICIT if we received a FocusIn for this 1154 /* Keep track of focus. May be EXPLICIT if we received a FocusIn for this
1080 frame, or IMPLICIT if we received an EnterNotify. 1155 frame, or IMPLICIT if we received an EnterNotify.
1081 FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */ 1156 FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT.
1157
1158 Not used when the input extension is being utilized. */
1082 int focus_state; 1159 int focus_state;
1083 1160
1084 /* The offset we need to add to compensate for type A WMs. */ 1161 /* The offset we need to add to compensate for type A WMs. */
@@ -1500,6 +1577,9 @@ extern void x_make_frame_invisible (struct frame *);
1500extern void x_iconify_frame (struct frame *); 1577extern void x_iconify_frame (struct frame *);
1501extern void x_free_frame_resources (struct frame *); 1578extern void x_free_frame_resources (struct frame *);
1502extern void x_wm_set_size_hint (struct frame *, long, bool); 1579extern void x_wm_set_size_hint (struct frame *, long, bool);
1580#if defined HAVE_XSYNCTRIGGERFENCE && !defined USE_GTK
1581extern void x_sync_init_fences (struct frame *);
1582#endif
1503 1583
1504extern void x_delete_terminal (struct terminal *); 1584extern void x_delete_terminal (struct terminal *);
1505extern Cursor x_create_font_cursor (struct x_display_info *, int); 1585extern Cursor x_create_font_cursor (struct x_display_info *, int);
@@ -1541,11 +1621,14 @@ extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t);
1541#ifdef HAVE_XRENDER 1621#ifdef HAVE_XRENDER
1542extern void x_xrender_color_from_gc_background (struct frame *, GC, 1622extern void x_xrender_color_from_gc_background (struct frame *, GC,
1543 XRenderColor *, bool); 1623 XRenderColor *, bool);
1544extern void x_xr_ensure_picture (struct frame *f); 1624extern void x_xr_ensure_picture (struct frame *);
1545extern void x_xr_apply_ext_clip (struct frame *f, GC gc); 1625extern void x_xr_apply_ext_clip (struct frame *, GC);
1546extern void x_xr_reset_ext_clip (struct frame *f); 1626extern void x_xr_reset_ext_clip (struct frame *);
1547#endif 1627#endif
1548 1628
1629extern Bool x_query_pointer (Display *, Window, Window *, Window *, int *,
1630 int *, int *, int *, unsigned int *);
1631
1549#ifdef HAVE_GTK3 1632#ifdef HAVE_GTK3
1550extern void x_scroll_bar_configure (GdkEvent *); 1633extern void x_scroll_bar_configure (GdkEvent *);
1551#endif 1634#endif