aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2021-12-17 14:23:07 +0800
committerPo Lu2021-12-17 14:23:07 +0800
commit5e5cde55e5be6e2d388252c3ccb0d019aee6b89e (patch)
tree339463076073de968bfe854c4813f0d47b6e34d5
parent32b9b22f66b1afcc614d5f76860d56d5630c5bc4 (diff)
parentf6339412eebdc027b00263ae2b5c38a029e2f7b4 (diff)
downloademacs-5e5cde55e5be6e2d388252c3ccb0d019aee6b89e.tar.gz
emacs-5e5cde55e5be6e2d388252c3ccb0d019aee6b89e.zip
Merge remote-tracking branch 'origin/master' into feature/pgtk
-rw-r--r--doc/lispref/commands.texi55
-rw-r--r--doc/lispref/os.texi7
-rw-r--r--etc/NEWS12
-rw-r--r--lisp/arc-mode.el8
-rw-r--r--lisp/calendar/icalendar.el4
-rw-r--r--lisp/epa-ks.el12
-rw-r--r--lisp/gnus/gnus-search.el8
-rw-r--r--lisp/gnus/nndiary.el4
-rw-r--r--lisp/gnus/nnrss.el16
-rw-r--r--lisp/net/soap-client.el7
-rw-r--r--lisp/net/tramp-adb.el4
-rw-r--r--lisp/org/ol.el2
-rw-r--r--lisp/org/org-clock.el12
-rw-r--r--lisp/org/org-colview.el2
-rw-r--r--lisp/org/org-macro.el2
-rw-r--r--lisp/org/org-macs.el4
-rw-r--r--lisp/org/org-table.el2
-rw-r--r--lisp/org/org.el8
-rw-r--r--lisp/org/ox-icalendar.el7
-rw-r--r--lisp/progmodes/project.el1
-rw-r--r--lisp/tar-mode.el4
-rw-r--r--lisp/time.el2
-rw-r--r--lisp/timezone.el9
-rw-r--r--lisp/vc/vc-dispatcher.el21
-rw-r--r--src/keyboard.c43
-rw-r--r--src/systime.h3
-rw-r--r--src/termhooks.h13
-rw-r--r--src/timefns.c73
-rw-r--r--src/xfns.c21
-rw-r--r--src/xterm.c604
-rw-r--r--src/xterm.h11
31 files changed, 643 insertions, 338 deletions
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index cc1c216d578..136fa56987b 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -1175,6 +1175,7 @@ intended by Lisp code to be used as an event.
1175* Button-Down Events:: A button was pushed and not yet released. 1175* Button-Down Events:: A button was pushed and not yet released.
1176* Repeat Events:: Double and triple click (or drag, or down). 1176* Repeat Events:: Double and triple click (or drag, or down).
1177* Motion Events:: Just moving the mouse, not pushing a button. 1177* Motion Events:: Just moving the mouse, not pushing a button.
1178* Touchscreen Events:: Tapping and moving fingers on a touchscreen.
1178* Focus Events:: Moving the mouse between frames. 1179* Focus Events:: Moving the mouse between frames.
1179* Xwidget Events:: Events generated by xwidgets. 1180* Xwidget Events:: Events generated by xwidgets.
1180* Misc Events:: Other events the system can generate. 1181* Misc Events:: Other events the system can generate.
@@ -1835,6 +1836,60 @@ small movements. Otherwise, motion events are not generated as long
1835as the mouse cursor remains pointing to the same glyph in the text. 1836as the mouse cursor remains pointing to the same glyph in the text.
1836@end defvar 1837@end defvar
1837 1838
1839@node Touchscreen Events
1840@subsection Touchscreen Events
1841@cindex touchscreen events
1842@cindex support for touchscreens
1843
1844Some window systems provide support for input devices that react to
1845the user's finger, and translate those finger movements into points at
1846an on-screen position. These input devices are known as touchscreens,
1847and Emacs reports the movements they generate as @dfn{touchscreen
1848events}.
1849
1850Most individual events generated by a touchscreen only have meaning as
1851part of a larger sequence of other events: for instance, the simple
1852operation of tapping the touchscreen involves the user placing and
1853releasing a finger on the touchscreen, and swiping the display to
1854scroll it involves placing a finger, moving it many times upwards or
1855downwards, and then releasing the finger.
1856
1857While a simplistic model consisting of one finger is adequate for taps
1858and scrolling, more complicated gestures require support for keeping
1859track of multiple fingers, where the position of each finger is
1860represented by a @dfn{touch point}. For example, a ``pinch to zoom''
1861gesture might consist of the user placing two fingers and moving them
1862individually in opposite directions, where the distance between the
1863positions of their individual points determine the amount by which to
1864zoom the display, and the center of an imaginary line between those
1865positions determines where to pan the display after zooming.
1866
1867@cindex touch point representation
1868The low-level touchscreen events described below can be used to
1869implement all the touch sequences described above. In those events,
1870each point is represented by a cons of an arbitrary number identifying
1871the point and a mouse position list (@pxref{Click Events}) specifying
1872the position of the finger when the event occurred.
1873
1874@table @code
1875@cindex @code{touchscreen-begin} event
1876@item (touchscreen-begin @var{point})
1877This event is sent when @var{point} is created by the user pressing a
1878finger against the touchscreen.
1879
1880@cindex @code{touchscreen-update} event
1881@item (touchscreen-update @var{points})
1882This event is sent when an point on the touchscreen has changed
1883position. @var{points} is a list of touchpoints containing the
1884up-to-date positions of each touchpoint currently on the touchscreen.
1885
1886@cindex @code{touchscreen-end} event
1887@item (touchscreen-end @var{point})
1888This event is sent when @var{point} is no longer present on the
1889display, because another program took the grab, or because the user
1890released the finger.
1891@end table
1892
1838@node Focus Events 1893@node Focus Events
1839@subsection Focus Events 1894@subsection Focus Events
1840@cindex focus event 1895@cindex focus event
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index b4efc44b039..de76ab4884a 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1352,7 +1352,7 @@ may change as higher-resolution clocks become available.
1352 1352
1353@cindex time value 1353@cindex time value
1354 Function arguments, e.g., the @var{time} argument to 1354 Function arguments, e.g., the @var{time} argument to
1355@code{current-time-string}, accept a more-general @dfn{time value} 1355@code{format-time-string}, accept a more-general @dfn{time value}
1356format, which can be a Lisp timestamp, @code{nil} for the current 1356format, which can be a Lisp timestamp, @code{nil} for the current
1357time, a single floating-point number for seconds, or a list 1357time, a single floating-point number for seconds, or a list
1358@code{(@var{high} @var{low} @var{micro})} or @code{(@var{high} 1358@code{(@var{high} @var{low} @var{micro})} or @code{(@var{high}
@@ -1507,10 +1507,7 @@ The optional @var{form} argument specifies the timestamp form to be
1507returned. If @var{form} is the symbol @code{integer}, this function 1507returned. If @var{form} is the symbol @code{integer}, this function
1508returns an integer count of seconds. If @var{form} is a positive 1508returns an integer count of seconds. If @var{form} is a positive
1509integer, it specifies a clock frequency and this function returns an 1509integer, it specifies a clock frequency and this function returns an
1510integer-pair timestamp @code{(@var{ticks} 1510integer-pair timestamp @code{(@var{ticks} . @var{form})}. If @var{form} is
1511. @var{form})}.@footnote{Currently a positive integer @var{form}
1512should be at least 65536 if the returned value is intended to be given
1513to standard functions expecting Lisp timestamps.} If @var{form} is
1514@code{t}, this function treats it as a positive integer suitable for 1511@code{t}, this function treats it as a positive integer suitable for
1515representing the timestamp; for example, it is treated as 1000000000 1512representing the timestamp; for example, it is treated as 1000000000
1516if @var{time} is nil and the platform timestamp has nanosecond 1513if @var{time} is nil and the platform timestamp has nanosecond
diff --git a/etc/NEWS b/etc/NEWS
index 1d78f1f5c3b..61e1cd12af9 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1152,10 +1152,22 @@ cookies set by web pages on disk.
1152This variable is bound to t during the preparation of a "*Help*" buffer. 1152This variable is bound to t during the preparation of a "*Help*" buffer.
1153 1153
1154+++ 1154+++
1155** Timestamps like (1 . 1000) now work without warnings being generated.
1156For example, (time-add nil '(1 . 1000)) no longer warns that the
1157(1 . 1000) acts like (1000 . 1000000). This warning, which was a
1158temporary transition aid for Emacs 27, has served its purpose.
1159
1160+++
1155** 'date-to-time' now assumes earliest values if its argument lacks 1161** 'date-to-time' now assumes earliest values if its argument lacks
1156month, day, or time. For example, (date-to-time "2021-12-04") now 1162month, day, or time. For example, (date-to-time "2021-12-04") now
1157assumes a time of 00:00 instead of signaling an error. 1163assumes a time of 00:00 instead of signaling an error.
1158 1164
1165+++
1166** New events for taking advantage of touchscreen devices.
1167The events 'touchscreen-down', 'touchscreen-update' and
1168'touchscreen-end' have been added to take better advantage of
1169touch-capable display panels.
1170
1159 1171
1160* Changes in Emacs 29.1 on Non-Free Operating Systems 1172* Changes in Emacs 29.1 on Non-Free Operating Systems
1161 1173
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index 1fd1d66c360..ece30fec003 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -617,12 +617,8 @@ OLDMODE will be modified accordingly just like chmod(2) would have done."
617 617
618(defun archive-unixdate (low high) 618(defun archive-unixdate (low high)
619 "Stringify Unix (LOW HIGH) date." 619 "Stringify Unix (LOW HIGH) date."
620 (let* ((time (list high low)) 620 (let ((system-time-locale "C"))
621 (str (current-time-string time))) 621 (format-time-string "%e-%b-%Y" (list high low))))
622 (format "%s-%s-%s"
623 (substring str 8 10)
624 (substring str 4 7)
625 (format-time-string "%Y" time))))
626 622
627(defun archive-unixtime (low high) 623(defun archive-unixtime (low high)
628 "Stringify Unix (LOW HIGH) time." 624 "Stringify Unix (LOW HIGH) time."
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el
index 7a483d40627..15778ea14bc 100644
--- a/lisp/calendar/icalendar.el
+++ b/lisp/calendar/icalendar.el
@@ -645,10 +645,10 @@ FIXME: multiple comma-separated values should be allowed!"
645 (setq second (read (substring isodatetimestring 13 15)))) 645 (setq second (read (substring isodatetimestring 13 15))))
646 ;; FIXME: Support subseconds. 646 ;; FIXME: Support subseconds.
647 (when (> (length isodatetimestring) 15) 647 (when (> (length isodatetimestring) 15)
648 (cl-case (aref isodatetimestring 15) 648 (pcase (aref isodatetimestring 15)
649 (?Z 649 (?Z
650 (setq source-zone t)) 650 (setq source-zone t))
651 ((?- ?+) 651 ((or ?- ?+)
652 (setq source-zone 652 (setq source-zone
653 (concat "UTC" (substring isodatetimestring 15)))))) 653 (concat "UTC" (substring isodatetimestring 15))))))
654 ;; shift if necessary 654 ;; shift if necessary
diff --git a/lisp/epa-ks.el b/lisp/epa-ks.el
index 5dd6ad34d74..186b0ac9d1c 100644
--- a/lisp/epa-ks.el
+++ b/lisp/epa-ks.el
@@ -295,12 +295,12 @@ enough, since keyservers have strict timeout settings."
295 :created 295 :created
296 (and (match-string 4) 296 (and (match-string 4)
297 (not (string-empty-p (match-string 4))) 297 (not (string-empty-p (match-string 4)))
298 (seconds-to-time 298 (time-convert
299 (string-to-number (match-string 4)))) 299 (string-to-number (match-string 4))))
300 :expires 300 :expires
301 (and (match-string 5) 301 (and (match-string 5)
302 (not (string-empty-p (match-string 5))) 302 (not (string-empty-p (match-string 5)))
303 (seconds-to-time 303 (time-convert
304 (string-to-number (match-string 5)))) 304 (string-to-number (match-string 5))))
305 :flags 305 :flags
306 (mapcar (lambda (flag) 306 (mapcar (lambda (flag)
@@ -319,15 +319,11 @@ enough, since keyservers have strict timeout settings."
319 :created 319 :created
320 (and (match-string 2) 320 (and (match-string 2)
321 (not (string-empty-p (match-string 2))) 321 (not (string-empty-p (match-string 2)))
322 (decode-time (seconds-to-time 322 (decode-time (string-to-number (match-string 2))))
323 (string-to-number
324 (match-string 2)))))
325 :expires 323 :expires
326 (and (match-string 3) 324 (and (match-string 3)
327 (not (string-empty-p (match-string 3))) 325 (not (string-empty-p (match-string 3)))
328 (decode-time (seconds-to-time 326 (decode-time (string-to-number (match-string 3))))
329 (string-to-number
330 (match-string 3)))))
331 :flags 327 :flags
332 (mapcar (lambda (flag) 328 (mapcar (lambda (flag)
333 (cdr (assq flag '((?r revoked) 329 (cdr (assq flag '((?r revoked)
diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el
index a79c106062c..46dc1cf6c1f 100644
--- a/lisp/gnus/gnus-search.el
+++ b/lisp/gnus/gnus-search.el
@@ -578,7 +578,7 @@ REL-DATE, or (current-time) if REL-DATE is nil."
578 (seq-subseq 578 (seq-subseq
579 (decode-time 579 (decode-time
580 (time-subtract 580 (time-subtract
581 (apply #'encode-time now) 581 (encode-time now)
582 (days-to-time 582 (days-to-time
583 (* (string-to-number (match-string 1 value)) 583 (* (string-to-number (match-string 1 value))
584 (cdr (assoc (match-string 2 value) 584 (cdr (assoc (match-string 2 value)
@@ -597,7 +597,7 @@ REL-DATE, or (current-time) if REL-DATE is nil."
597 ;; If DOW is given, handle that specially. 597 ;; If DOW is given, handle that specially.
598 (if (and (seq-elt d-time 6) (null (seq-elt d-time 3))) 598 (if (and (seq-elt d-time 6) (null (seq-elt d-time 3)))
599 (decode-time 599 (decode-time
600 (time-subtract (apply #'encode-time now) 600 (time-subtract (encode-time now)
601 (days-to-time 601 (days-to-time
602 (+ (if (> (seq-elt d-time 6) 602 (+ (if (> (seq-elt d-time 6)
603 (seq-elt now 6)) 603 (seq-elt now 6))
@@ -1257,9 +1257,7 @@ elements are present."
1257 (setq dmonth 1)))) 1257 (setq dmonth 1))))
1258 (format-time-string 1258 (format-time-string
1259 "%e-%b-%Y" 1259 "%e-%b-%Y"
1260 (apply #'encode-time 1260 (encode-time 0 0 0 dday dmonth dyear))))
1261 (append '(0 0 0)
1262 (list dday dmonth dyear))))))
1263 1261
1264(cl-defmethod gnus-search-imap-handle-string ((engine gnus-search-imap) 1262(cl-defmethod gnus-search-imap-handle-string ((engine gnus-search-imap)
1265 (str string)) 1263 (str string))
diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el
index 133e0307a54..6f8917e2528 100644
--- a/lisp/gnus/nndiary.el
+++ b/lisp/gnus/nndiary.el
@@ -1308,7 +1308,7 @@ all. This may very well take some time.")
1308 (let ((minute (nndiary-max (nth 0 sched))) 1308 (let ((minute (nndiary-max (nth 0 sched)))
1309 (hour (nndiary-max (nth 1 sched))) 1309 (hour (nndiary-max (nth 1 sched)))
1310 (year (nndiary-max (nth 4 sched))) 1310 (year (nndiary-max (nth 4 sched)))
1311 (time-zone (or (and (nth 6 sched) (car (nth 6 sched))) 1311 (time-zone (or (car (nth 6 sched))
1312 (current-time-zone)))) 1312 (current-time-zone))))
1313 (when year 1313 (when year
1314 (or minute (setq minute 59)) 1314 (or minute (setq minute 59))
@@ -1405,7 +1405,7 @@ all. This may very well take some time.")
1405 t)) 1405 t))
1406 (dow-list (nth 5 sched)) 1406 (dow-list (nth 5 sched))
1407 (year (1- this-year)) 1407 (year (1- this-year))
1408 (time-zone (or (and (nth 6 sched) (car (nth 6 sched))) 1408 (time-zone (or (car (nth 6 sched))
1409 (current-time-zone)))) 1409 (current-time-zone))))
1410 ;; Special case: an asterisk in one of the days specifications means that 1410 ;; Special case: an asterisk in one of the days specifications means that
1411 ;; only the other should be taken into account. If both are unspecified, 1411 ;; only the other should be taken into account. If both are unspecified,
diff --git a/lisp/gnus/nnrss.el b/lisp/gnus/nnrss.el
index 0ac57e9e171..59a22f725a9 100644
--- a/lisp/gnus/nnrss.el
+++ b/lisp/gnus/nnrss.el
@@ -450,7 +450,7 @@ nnrss: %s: Not valid XML %s and libxml-parse-html-region doesn't work %s"
450This function handles the ISO 8601 date format described in 450This function handles the ISO 8601 date format described in
451URL `https://www.w3.org/TR/NOTE-datetime', and also the RFC 822 style 451URL `https://www.w3.org/TR/NOTE-datetime', and also the RFC 822 style
452which RSS 2.0 allows." 452which RSS 2.0 allows."
453 (let (case-fold-search vector year month day time zone cts given) 453 (let (case-fold-search vector year month day time zone given)
454 (cond ((null date)) ; do nothing for this case 454 (cond ((null date)) ; do nothing for this case
455 ;; if the date is just digits (unix time stamp): 455 ;; if the date is just digits (unix time stamp):
456 ((string-match "^[0-9]+$" date) 456 ((string-match "^[0-9]+$" date)
@@ -481,13 +481,13 @@ which RSS 2.0 allows."
481 0 481 0
482 (decoded-time-zone decoded)))))) 482 (decoded-time-zone decoded))))))
483 (if month 483 (if month
484 (progn 484 (concat (let ((system-time-locale "C"))
485 (setq cts (current-time-string (encode-time 0 0 0 day month year))) 485 (format-time-string "%a, %d %b %Y "
486 (format "%s, %02d %s %04d %s%s" 486 (encode-time 0 0 0 day month year)))
487 (substring cts 0 3) day (substring cts 4 7) year time 487 time
488 (if zone 488 (if zone
489 (concat " " (format-time-string "%z" nil zone)) 489 (format-time-string " %z" nil zone)
490 ""))) 490 ""))
491 (message-make-date given)))) 491 (message-make-date given))))
492 492
493;;; data functions 493;;; data functions
diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el
index b4aed279819..6f915e97452 100644
--- a/lisp/net/soap-client.el
+++ b/lisp/net/soap-client.el
@@ -718,10 +718,9 @@ representing leap seconds."
718 second) 718 second)
719 minute hour day month year second-fraction datatype time-zone) 719 minute hour day month year second-fraction datatype time-zone)
720 (let ((time 720 (let ((time
721 (apply 721 (encode-time (list
722 #'encode-time (list 722 (if new-decode-time new-decode-time-second second)
723 (if new-decode-time new-decode-time-second second) 723 minute hour day month year nil nil time-zone))))
724 minute hour day month year nil nil time-zone))))
725 (if new-decode-time 724 (if new-decode-time
726 (with-no-warnings (decode-time time nil t)) 725 (with-no-warnings (decode-time time nil t))
727 (decode-time time)))))) 726 (decode-time time))))))
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 341357d404c..bc94092ce95 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -416,9 +416,9 @@ Emacs dired can't find files."
416 "Sort \"ls\" output by time, descending." 416 "Sort \"ls\" output by time, descending."
417 (let (time-a time-b) 417 (let (time-a time-b)
418 (string-match tramp-adb-ls-date-regexp a) 418 (string-match tramp-adb-ls-date-regexp a)
419 (setq time-a (apply #'encode-time (parse-time-string (match-string 0 a)))) 419 (setq time-a (encode-time (parse-time-string (match-string 0 a))))
420 (string-match tramp-adb-ls-date-regexp b) 420 (string-match tramp-adb-ls-date-regexp b)
421 (setq time-b (apply #'encode-time (parse-time-string (match-string 0 b)))) 421 (setq time-b (encode-time (parse-time-string (match-string 0 b))))
422 (time-less-p time-b time-a))) 422 (time-less-p time-b time-a)))
423 423
424(defun tramp-adb-ls-output-name-less-p (a b) 424(defun tramp-adb-ls-output-name-less-p (a b)
diff --git a/lisp/org/ol.el b/lisp/org/ol.el
index aa1849715c3..b70f1996d54 100644
--- a/lisp/org/ol.el
+++ b/lisp/org/ol.el
@@ -1575,7 +1575,7 @@ non-nil."
1575 (setq link 1575 (setq link
1576 (format-time-string 1576 (format-time-string
1577 (car org-time-stamp-formats) 1577 (car org-time-stamp-formats)
1578 (apply 'encode-time 1578 (encode-time
1579 (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd) 1579 (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd)
1580 nil nil nil)))) 1580 nil nil nil))))
1581 (org-link-store-props :type "calendar" :date cd))) 1581 (org-link-store-props :type "calendar" :date cd)))
diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el
index 12a4c2b7b71..2526ca793aa 100644
--- a/lisp/org/org-clock.el
+++ b/lisp/org/org-clock.el
@@ -1904,11 +1904,11 @@ PROPNAME lets you set a custom text property instead of :org-clock-minutes."
1904 ((match-end 2) 1904 ((match-end 2)
1905 ;; Two time stamps. 1905 ;; Two time stamps.
1906 (let* ((ts (float-time 1906 (let* ((ts (float-time
1907 (apply #'encode-time 1907 (encode-time
1908 (save-match-data 1908 (save-match-data
1909 (org-parse-time-string (match-string 2)))))) 1909 (org-parse-time-string (match-string 2))))))
1910 (te (float-time 1910 (te (float-time
1911 (apply #'encode-time 1911 (encode-time
1912 (org-parse-time-string (match-string 3))))) 1912 (org-parse-time-string (match-string 3)))))
1913 (dt (- (if tend (min te tend) te) 1913 (dt (- (if tend (min te tend) te)
1914 (if tstart (max ts tstart) ts)))) 1914 (if tstart (max ts tstart) ts))))
@@ -2837,7 +2837,7 @@ a number of clock tables."
2837 (pcase (if range (car range) (plist-get params :tstart)) 2837 (pcase (if range (car range) (plist-get params :tstart))
2838 ((and (pred numberp) n) 2838 ((and (pred numberp) n)
2839 (pcase-let ((`(,m ,d ,y) (calendar-gregorian-from-absolute n))) 2839 (pcase-let ((`(,m ,d ,y) (calendar-gregorian-from-absolute n)))
2840 (apply #'encode-time (list 0 0 org-extend-today-until d m y)))) 2840 (encode-time 0 0 org-extend-today-until d m y)))
2841 (timestamp 2841 (timestamp
2842 (seconds-to-time 2842 (seconds-to-time
2843 (org-matcher-time (or timestamp 2843 (org-matcher-time (or timestamp
@@ -2847,7 +2847,7 @@ a number of clock tables."
2847 (pcase (if range (nth 1 range) (plist-get params :tend)) 2847 (pcase (if range (nth 1 range) (plist-get params :tend))
2848 ((and (pred numberp) n) 2848 ((and (pred numberp) n)
2849 (pcase-let ((`(,m ,d ,y) (calendar-gregorian-from-absolute n))) 2849 (pcase-let ((`(,m ,d ,y) (calendar-gregorian-from-absolute n)))
2850 (apply #'encode-time (list 0 0 org-extend-today-until d m y)))) 2850 (encode-time 0 0 org-extend-today-until d m y)))
2851 (timestamp (seconds-to-time (org-matcher-time timestamp)))))) 2851 (timestamp (seconds-to-time (org-matcher-time timestamp))))))
2852 (while (time-less-p start end) 2852 (while (time-less-p start end)
2853 (unless (bolp) (insert "\n")) 2853 (unless (bolp) (insert "\n"))
@@ -3042,9 +3042,9 @@ Otherwise, return nil."
3042 (setq ts (match-string 1) 3042 (setq ts (match-string 1)
3043 te (match-string 3)) 3043 te (match-string 3))
3044 (setq s (- (float-time 3044 (setq s (- (float-time
3045 (apply #'encode-time (org-parse-time-string te))) 3045 (encode-time (org-parse-time-string te)))
3046 (float-time 3046 (float-time
3047 (apply #'encode-time (org-parse-time-string ts)))) 3047 (encode-time (org-parse-time-string ts))))
3048 neg (< s 0) 3048 neg (< s 0)
3049 s (abs s) 3049 s (abs s)
3050 h (floor (/ s 3600)) 3050 h (floor (/ s 3600))
diff --git a/lisp/org/org-colview.el b/lisp/org/org-colview.el
index 9794382d8a4..f93e948bdcd 100644
--- a/lisp/org/org-colview.el
+++ b/lisp/org/org-colview.el
@@ -782,7 +782,7 @@ around it."
782 (setq time-after (copy-sequence time)) 782 (setq time-after (copy-sequence time))
783 (setf (nth 3 time-before) (1- (nth 3 time))) 783 (setf (nth 3 time-before) (1- (nth 3 time)))
784 (setf (nth 3 time-after) (1+ (nth 3 time))) 784 (setf (nth 3 time-after) (1+ (nth 3 time)))
785 (mapcar (lambda (x) (format-time-string fmt (apply #'encode-time x))) 785 (mapcar (lambda (x) (format-time-string fmt (encode-time x)))
786 (list time-before time time-after))))) 786 (list time-before time time-after)))))
787 787
788(defun org-columns-open-link (&optional arg) 788(defun org-columns-open-link (&optional arg)
diff --git a/lisp/org/org-macro.el b/lisp/org/org-macro.el
index c0287a25a55..83c35faea41 100644
--- a/lisp/org/org-macro.el
+++ b/lisp/org/org-macro.el
@@ -378,7 +378,7 @@ Return value as a string."
378 (buffer-substring 378 (buffer-substring
379 (point) (line-end-position))))) 379 (point) (line-end-position)))))
380 (when (cl-some #'identity time) 380 (when (cl-some #'identity time)
381 (setq date (apply #'encode-time time)))))))) 381 (setq date (encode-time time))))))))
382 (let ((proc (get-buffer-process buf))) 382 (let ((proc (get-buffer-process buf)))
383 (while (and proc (accept-process-output proc .5 nil t))))) 383 (while (and proc (accept-process-output proc .5 nil t)))))
384 (kill-buffer buf)) 384 (kill-buffer buf))
diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el
index 0779c3a82c8..044056b7a04 100644
--- a/lisp/org/org-macs.el
+++ b/lisp/org/org-macs.el
@@ -1185,7 +1185,7 @@ nil, just return 0."
1185 ((numberp s) s) 1185 ((numberp s) s)
1186 ((stringp s) 1186 ((stringp s)
1187 (condition-case nil 1187 (condition-case nil
1188 (float-time (apply #'encode-time (org-parse-time-string s))) 1188 (float-time (encode-time (org-parse-time-string s)))
1189 (error 0))) 1189 (error 0)))
1190 (t 0))) 1190 (t 0)))
1191 1191
@@ -1252,7 +1252,7 @@ following special strings: \"<now>\", \"<today>\",
1252\"<tomorrow>\", and \"<yesterday>\". 1252\"<tomorrow>\", and \"<yesterday>\".
1253 1253
1254Return 0. if S is not recognized as a valid value." 1254Return 0. if S is not recognized as a valid value."
1255 (let ((today (float-time (apply #'encode-time 1255 (let ((today (float-time (encode-time
1256 (append '(0 0 0) (nthcdr 3 (decode-time))))))) 1256 (append '(0 0 0) (nthcdr 3 (decode-time)))))))
1257 (save-match-data 1257 (save-match-data
1258 (cond 1258 (cond
diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el
index e34872fb491..a6dd8bff20f 100644
--- a/lisp/org/org-table.el
+++ b/lisp/org/org-table.el
@@ -2606,7 +2606,7 @@ location of point."
2606 (format-time-string 2606 (format-time-string
2607 (org-time-stamp-format 2607 (org-time-stamp-format
2608 (string-match-p "[0-9]\\{1,2\\}:[0-9]\\{2\\}" ts)) 2608 (string-match-p "[0-9]\\{1,2\\}:[0-9]\\{2\\}" ts))
2609 (apply #'encode-time 2609 (encode-time
2610 (save-match-data (org-parse-time-string ts)))))) 2610 (save-match-data (org-parse-time-string ts))))))
2611 form t t)) 2611 form t t))
2612 2612
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 00bbc076881..253a9efa27c 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -13987,7 +13987,7 @@ user."
13987 (when (< (nth 2 org-defdecode) org-extend-today-until) 13987 (when (< (nth 2 org-defdecode) org-extend-today-until)
13988 (setf (nth 2 org-defdecode) -1) 13988 (setf (nth 2 org-defdecode) -1)
13989 (setf (nth 1 org-defdecode) 59) 13989 (setf (nth 1 org-defdecode) 59)
13990 (setq org-def (apply #'encode-time org-defdecode)) 13990 (setq org-def (encode-time org-defdecode))
13991 (setq org-defdecode (decode-time org-def))) 13991 (setq org-defdecode (decode-time org-def)))
13992 (let* ((timestr (format-time-string 13992 (let* ((timestr (format-time-string
13993 (if org-with-time "%Y-%m-%d %H:%M" "%Y-%m-%d") 13993 (if org-with-time "%Y-%m-%d %H:%M" "%Y-%m-%d")
@@ -14471,7 +14471,7 @@ The command returns the inserted time stamp."
14471 time (org-fix-decoded-time t1) 14471 time (org-fix-decoded-time t1)
14472 str (org-add-props 14472 str (org-add-props
14473 (format-time-string 14473 (format-time-string
14474 (substring tf 1 -1) (apply 'encode-time time)) 14474 (substring tf 1 -1) (encode-time time))
14475 nil 'mouse-face 'highlight)) 14475 nil 'mouse-face 'highlight))
14476 (put-text-property beg end 'display str))) 14476 (put-text-property beg end 'display str)))
14477 14477
@@ -14726,7 +14726,7 @@ days in order to avoid rounding problems."
14726 14726
14727(defun org-time-string-to-time (s) 14727(defun org-time-string-to-time (s)
14728 "Convert timestamp string S into internal time." 14728 "Convert timestamp string S into internal time."
14729 (apply #'encode-time (org-parse-time-string s))) 14729 (encode-time (org-parse-time-string s)))
14730 14730
14731(defun org-time-string-to-seconds (s) 14731(defun org-time-string-to-seconds (s)
14732 "Convert a timestamp string S into a number of seconds." 14732 "Convert a timestamp string S into a number of seconds."
@@ -15156,7 +15156,7 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like
15156 (setcar time0 (or (car time0) 0)) 15156 (setcar time0 (or (car time0) 0))
15157 (setcar (nthcdr 1 time0) (or (nth 1 time0) 0)) 15157 (setcar (nthcdr 1 time0) (or (nth 1 time0) 0))
15158 (setcar (nthcdr 2 time0) (or (nth 2 time0) 0)) 15158 (setcar (nthcdr 2 time0) (or (nth 2 time0) 0))
15159 (setq time (apply 'encode-time time0)))) 15159 (setq time (encode-time time0))))
15160 ;; Insert the new time-stamp, and ensure point stays in the same 15160 ;; Insert the new time-stamp, and ensure point stays in the same
15161 ;; category as before (i.e. not after the last position in that 15161 ;; category as before (i.e. not after the last position in that
15162 ;; category). 15162 ;; category).
diff --git a/lisp/org/ox-icalendar.el b/lisp/org/ox-icalendar.el
index 16c3dc9a029..211d0f716b8 100644
--- a/lisp/org/ox-icalendar.el
+++ b/lisp/org/ox-icalendar.el
@@ -824,8 +824,7 @@ as a communication channel."
824 (if (not (plist-get info :with-author)) "" 824 (if (not (plist-get info :with-author)) ""
825 (org-export-data (plist-get info :author) info)) 825 (org-export-data (plist-get info :author) info))
826 ;; Timezone. 826 ;; Timezone.
827 (if (org-string-nw-p org-icalendar-timezone) org-icalendar-timezone 827 (or (org-string-nw-p org-icalendar-timezone) (format-time-string "%Z"))
828 (cadr (current-time-zone)))
829 ;; Description. 828 ;; Description.
830 (org-export-data (plist-get info :title) info) 829 (org-export-data (plist-get info :title) info)
831 contents)) 830 contents))
@@ -972,7 +971,7 @@ This function assumes major mode for current buffer is
972 (org-icalendar--vcalendar 971 (org-icalendar--vcalendar
973 org-icalendar-combined-name 972 org-icalendar-combined-name
974 user-full-name 973 user-full-name
975 (or (org-string-nw-p org-icalendar-timezone) (cadr (current-time-zone))) 974 (or (org-string-nw-p org-icalendar-timezone) (format-time-string "%Z"))
976 org-icalendar-combined-description 975 org-icalendar-combined-description
977 contents))) 976 contents)))
978 (run-hook-with-args 'org-icalendar-after-save-hook file))) 977 (run-hook-with-args 'org-icalendar-after-save-hook file)))
@@ -995,7 +994,7 @@ FILES is a list of files to build the calendar from."
995 user-full-name 994 user-full-name
996 ;; Timezone. 995 ;; Timezone.
997 (or (org-string-nw-p org-icalendar-timezone) 996 (or (org-string-nw-p org-icalendar-timezone)
998 (cadr (current-time-zone))) 997 (format-time-string "Z"))
999 ;; Description. 998 ;; Description.
1000 org-icalendar-combined-description 999 org-icalendar-combined-description
1001 ;; Contents. 1000 ;; Contents.
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 8fecdbb61cf..3b634471ace 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1175,6 +1175,7 @@ displayed."
1175 (derived-mode . dired-mode) 1175 (derived-mode . dired-mode)
1176 (derived-mode . diff-mode) 1176 (derived-mode . diff-mode)
1177 (derived-mode . comint-mode) 1177 (derived-mode . comint-mode)
1178 (derived-mode . eshell-mode)
1178 (derived-mode . change-log-mode)) 1179 (derived-mode . change-log-mode))
1179 "List of conditions to kill buffers related to a project. 1180 "List of conditions to kill buffers related to a project.
1180This list is used by `project-kill-buffers'. 1181This list is used by `project-kill-buffers'.
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
index db655619bed..0ca26f770c4 100644
--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -467,8 +467,8 @@ checksum before doing the check."
467 467
468(defun tar-clip-time-string (time) 468(defun tar-clip-time-string (time)
469 (declare (obsolete format-time-string "27.1")) 469 (declare (obsolete format-time-string "27.1"))
470 (let ((str (current-time-string time))) 470 (let ((system-time-locale "C"))
471 (concat " " (substring str 4 16) (format-time-string " %Y" time)))) 471 (format-time-string " %b %e %H:%M %Y" time)))
472 472
473(defun tar-grind-file-mode (mode) 473(defun tar-grind-file-mode (mode)
474 "Construct a `rw-r--r--' string indicating MODE. 474 "Construct a `rw-r--r--' string indicating MODE.
diff --git a/lisp/time.el b/lisp/time.el
index fcea064b4cf..b67315cf630 100644
--- a/lisp/time.el
+++ b/lisp/time.el
@@ -355,7 +355,7 @@ update which can wait for the next redisplay."
355 (am-pm (if (>= hour 12) "pm" "am")) 355 (am-pm (if (>= hour 12) "pm" "am"))
356 (minutes (substring time 14 16)) 356 (minutes (substring time 14 16))
357 (seconds (substring time 17 19)) 357 (seconds (substring time 17 19))
358 (time-zone (car (cdr (current-time-zone now)))) 358 (time-zone (format-time-string "%Z" now))
359 (day (substring time 8 10)) 359 (day (substring time 8 10))
360 (year (format-time-string "%Y" now)) 360 (year (format-time-string "%Y" now))
361 (monthname (substring time 4 7)) 361 (monthname (substring time 4 7))
diff --git a/lisp/timezone.el b/lisp/timezone.el
index 0fcdbdbc16c..7a461c4e22d 100644
--- a/lisp/timezone.el
+++ b/lisp/timezone.el
@@ -299,11 +299,10 @@ Return a list in the same format as `current-time-zone's result,
299or nil if the local time zone could not be computed. 299or nil if the local time zone could not be computed.
300DATE is the number of days elapsed since the (imaginary) 300DATE is the number of days elapsed since the (imaginary)
301Gregorian date Sunday, December 31, 1 BC." 301Gregorian date Sunday, December 31, 1 BC."
302 (and (fboundp 'current-time-zone) 302 (let ((utc-time (timezone-time-from-absolute date seconds)))
303 (let ((utc-time (timezone-time-from-absolute date seconds))) 303 (and utc-time
304 (and utc-time 304 (let ((zone (current-time-zone utc-time)))
305 (let ((zone (current-time-zone utc-time))) 305 (and (car zone) zone)))))
306 (and (car zone) zone))))))
307 306
308(defun timezone-fix-time (date local timezone) 307(defun timezone-fix-time (date local timezone)
309 "Convert DATE (default timezone LOCAL) to YYYY-MM-DD-HH-MM-SS-ZONE vector. 308 "Convert DATE (default timezone LOCAL) to YYYY-MM-DD-HH-MM-SS-ZONE vector.
diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el
index 346974bdba8..53cdb5eba84 100644
--- a/lisp/vc/vc-dispatcher.el
+++ b/lisp/vc/vc-dispatcher.el
@@ -127,8 +127,12 @@ preserve the setting."
127 :group 'vc) 127 :group 'vc)
128 128
129(defcustom vc-command-messages nil 129(defcustom vc-command-messages nil
130 "If non-nil, display run messages from back-end commands." 130 "If non-nil, display and log messages about running back-end commands.
131 :type 'boolean 131If the value is `log', messages about running VC back-end commands are
132logged in the *Messages* buffer, but not displayed."
133 :type '(choice (const :tag "No messages" nil)
134 (const :tag "Display and log messages" t)
135 (const :tag "Log messages, but don't display" log))
132 :group 'vc) 136 :group 'vc)
133 137
134(defcustom vc-suppress-confirm nil 138(defcustom vc-suppress-confirm nil
@@ -311,7 +315,10 @@ case, and the process object in the asynchronous case."
311 (substring command 0 -1) 315 (substring command 0 -1)
312 command) 316 command)
313 " " (vc-delistify flags) 317 " " (vc-delistify flags)
314 " " (vc-delistify files)))) 318 " " (vc-delistify files)))
319 (vc-inhibit-message
320 (or (eq vc-command-messages 'log)
321 (eq (selected-window) (active-minibuffer-window)))))
315 (save-current-buffer 322 (save-current-buffer
316 (unless (or (eq buffer t) 323 (unless (or (eq buffer t)
317 (and (stringp buffer) 324 (and (stringp buffer)
@@ -335,7 +342,7 @@ case, and the process object in the asynchronous case."
335 (apply #'start-file-process command (current-buffer) 342 (apply #'start-file-process command (current-buffer)
336 command squeezed)))) 343 command squeezed))))
337 (when vc-command-messages 344 (when vc-command-messages
338 (let ((inhibit-message (eq (selected-window) (active-minibuffer-window)))) 345 (let ((inhibit-message vc-inhibit-message))
339 (message "Running in background: %s" full-command))) 346 (message "Running in background: %s" full-command)))
340 ;; Get rid of the default message insertion, in case we don't 347 ;; Get rid of the default message insertion, in case we don't
341 ;; set a sentinel explicitly. 348 ;; set a sentinel explicitly.
@@ -345,11 +352,11 @@ case, and the process object in the asynchronous case."
345 (when vc-command-messages 352 (when vc-command-messages
346 (vc-run-delayed 353 (vc-run-delayed
347 (let ((message-truncate-lines t) 354 (let ((message-truncate-lines t)
348 (inhibit-message (eq (selected-window) (active-minibuffer-window)))) 355 (inhibit-message vc-inhibit-message))
349 (message "Done in background: %s" full-command))))) 356 (message "Done in background: %s" full-command)))))
350 ;; Run synchronously 357 ;; Run synchronously
351 (when vc-command-messages 358 (when vc-command-messages
352 (let ((inhibit-message (eq (selected-window) (active-minibuffer-window)))) 359 (let ((inhibit-message vc-inhibit-message))
353 (message "Running in foreground: %s" full-command))) 360 (message "Running in foreground: %s" full-command)))
354 (let ((buffer-undo-list t)) 361 (let ((buffer-undo-list t))
355 (setq status (apply #'process-file command nil t nil squeezed))) 362 (setq status (apply #'process-file command nil t nil squeezed)))
@@ -364,7 +371,7 @@ case, and the process object in the asynchronous case."
364 (if (integerp status) (format "status %d" status) status) 371 (if (integerp status) (format "status %d" status) status)
365 full-command)) 372 full-command))
366 (when vc-command-messages 373 (when vc-command-messages
367 (let ((inhibit-message (eq (selected-window) (active-minibuffer-window)))) 374 (let ((inhibit-message vc-inhibit-message))
368 (message "Done (status=%d): %s" status full-command))))) 375 (message "Done (status=%d): %s" status full-command)))))
369 (vc-run-delayed 376 (vc-run-delayed
370 (run-hook-with-args 'vc-post-command-functions 377 (run-hook-with-args 'vc-post-command-functions
diff --git a/src/keyboard.c b/src/keyboard.c
index df07cf290b8..821a1b576be 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -6013,6 +6013,46 @@ make_lispy_event (struct input_event *event)
6013 return list2 (Qtouch_end, position); 6013 return list2 (Qtouch_end, position);
6014 } 6014 }
6015 6015
6016 case TOUCHSCREEN_BEGIN_EVENT:
6017 case TOUCHSCREEN_END_EVENT:
6018 {
6019 Lisp_Object x, y, id, position;
6020 struct frame *f = XFRAME (event->frame_or_window);
6021
6022 id = event->arg;
6023 x = event->x;
6024 y = event->y;
6025
6026 position = make_lispy_position (f, x, y, event->timestamp);
6027
6028 return list2 (((event->kind
6029 == TOUCHSCREEN_BEGIN_EVENT)
6030 ? Qtouchscreen_begin
6031 : Qtouchscreen_end),
6032 Fcons (id, position));
6033 }
6034
6035 case TOUCHSCREEN_UPDATE_EVENT:
6036 {
6037 Lisp_Object x, y, id, position, tem, it, evt;
6038 struct frame *f = XFRAME (event->frame_or_window);
6039 evt = Qnil;
6040
6041 for (tem = event->arg; CONSP (tem); tem = XCDR (tem))
6042 {
6043 it = XCAR (tem);
6044
6045 x = XCAR (it);
6046 y = XCAR (XCDR (it));
6047 id = XCAR (XCDR (XCDR (it)));
6048
6049 position = make_lispy_position (f, x, y, event->timestamp);
6050 evt = Fcons (Fcons (id, position), evt);
6051 }
6052
6053 return list2 (Qtouchscreen_update, evt);
6054 }
6055
6016#ifdef USE_TOOLKIT_SCROLL_BARS 6056#ifdef USE_TOOLKIT_SCROLL_BARS
6017 6057
6018 /* We don't have down and up events if using toolkit scroll bars, 6058 /* We don't have down and up events if using toolkit scroll bars,
@@ -12266,6 +12306,9 @@ See also `pre-command-hook'. */);
12266 doc: /* Normal hook run when clearing the echo area. */); 12306 doc: /* Normal hook run when clearing the echo area. */);
12267#endif 12307#endif
12268 DEFSYM (Qecho_area_clear_hook, "echo-area-clear-hook"); 12308 DEFSYM (Qecho_area_clear_hook, "echo-area-clear-hook");
12309 DEFSYM (Qtouchscreen_begin, "touchscreen-begin");
12310 DEFSYM (Qtouchscreen_end, "touchscreen-end");
12311 DEFSYM (Qtouchscreen_update, "touchscreen-update");
12269 Fset (Qecho_area_clear_hook, Qnil); 12312 Fset (Qecho_area_clear_hook, Qnil);
12270 12313
12271 DEFVAR_LISP ("lucid-menu-bar-dirty-flag", Vlucid_menu_bar_dirty_flag, 12314 DEFVAR_LISP ("lucid-menu-bar-dirty-flag", Vlucid_menu_bar_dirty_flag,
diff --git a/src/systime.h b/src/systime.h
index 08ab5bdde33..ce9403c931d 100644
--- a/src/systime.h
+++ b/src/systime.h
@@ -80,8 +80,7 @@ struct lisp_time
80 /* Clock count as a Lisp integer. */ 80 /* Clock count as a Lisp integer. */
81 Lisp_Object ticks; 81 Lisp_Object ticks;
82 82
83 /* Clock frequency (ticks per second) as a positive Lisp integer. 83 /* Clock frequency (ticks per second) as a positive Lisp integer. */
84 (TICKS . HZ) is a valid Lisp timestamp unless HZ < 65536. */
85 Lisp_Object hz; 84 Lisp_Object hz;
86}; 85};
87 86
diff --git a/src/termhooks.h b/src/termhooks.h
index b124e995292..9f22187b841 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -280,6 +280,19 @@ enum event_kind
280 In the future, this may take into account other multi-touch 280 In the future, this may take into account other multi-touch
281 events generated from touchscreens and such. */ 281 events generated from touchscreens and such. */
282 , TOUCH_END_EVENT 282 , TOUCH_END_EVENT
283
284 /* In a TOUCHSCREEN_UPDATE_EVENT, ARG is a list of elements of the
285 form (X Y ID), where X and Y are the coordinates of the
286 touchpoint relative to the top-left corner of the frame, and ID
287 is a unique number identifying the touchpoint.
288
289 In TOUCHSCREEN_BEGIN_EVENT and TOUCHSCREEN_END_EVENT, ARG is the
290 unique ID of the touchpoint, and X and Y are the frame-relative
291 positions of the touchpoint. */
292
293 , TOUCHSCREEN_UPDATE_EVENT
294 , TOUCHSCREEN_BEGIN_EVENT
295 , TOUCHSCREEN_END_EVENT
283}; 296};
284 297
285/* Bit width of an enum event_kind tag at the start of structs and unions. */ 298/* Bit width of an enum event_kind tag at the start of structs and unions. */
diff --git a/src/timefns.c b/src/timefns.c
index a9921cdc108..74b5ca8d515 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -69,16 +69,6 @@ enum { TM_YEAR_BASE = 1900 };
69# define FASTER_TIMEFNS 1 69# define FASTER_TIMEFNS 1
70#endif 70#endif
71 71
72/* Whether to warn about Lisp timestamps (TICKS . HZ) that may be
73 instances of obsolete-format timestamps (HI . LO) where HI is
74 the high-order bits and LO the low-order 16 bits. Currently this
75 is true, but it should change to false in a future version of
76 Emacs. Compile with -DWARN_OBSOLETE_TIMESTAMPS=0 to see what the
77 future will be like. */
78#ifndef WARN_OBSOLETE_TIMESTAMPS
79enum { WARN_OBSOLETE_TIMESTAMPS = true };
80#endif
81
82/* Although current-time etc. generate list-format timestamps 72/* Although current-time etc. generate list-format timestamps
83 (HI LO US PS), the plan is to change these functions to generate 73 (HI LO US PS), the plan is to change these functions to generate
84 frequency-based timestamps (TICKS . HZ) in a future release. 74 frequency-based timestamps (TICKS . HZ) in a future release.
@@ -817,14 +807,10 @@ decode_time_components (enum timeform form,
817 return decode_ticks_hz (make_integer_mpz (), hz, result, dresult); 807 return decode_ticks_hz (make_integer_mpz (), hz, result, dresult);
818} 808}
819 809
820enum { DECODE_SECS_ONLY = WARN_OBSOLETE_TIMESTAMPS + 1 };
821
822/* Decode a Lisp timestamp SPECIFIED_TIME that represents a time. 810/* Decode a Lisp timestamp SPECIFIED_TIME that represents a time.
823 811
824 FLAGS specifies conversion flags. If FLAGS & DECODE_SECS_ONLY, 812 If DECODE_SECS_ONLY, ignore and do not validate any sub-second
825 ignore and do not validate any sub-second components of an 813 components of an old-format SPECIFIED_TIME.
826 old-format SPECIFIED_TIME. If FLAGS & WARN_OBSOLETE_TIMESTAMPS,
827 diagnose what could be obsolete (HIGH . LOW) timestamps.
828 814
829 If RESULT is not null, store into *RESULT the converted time; 815 If RESULT is not null, store into *RESULT the converted time;
830 otherwise, store into *DRESULT the number of seconds since the 816 otherwise, store into *DRESULT the number of seconds since the
@@ -833,7 +819,7 @@ enum { DECODE_SECS_ONLY = WARN_OBSOLETE_TIMESTAMPS + 1 };
833 819
834 Return the form of SPECIFIED-TIME. Signal an error if unsuccessful. */ 820 Return the form of SPECIFIED-TIME. Signal an error if unsuccessful. */
835static enum timeform 821static enum timeform
836decode_lisp_time (Lisp_Object specified_time, int flags, 822decode_lisp_time (Lisp_Object specified_time, bool decode_secs_only,
837 struct lisp_time *result, double *dresult) 823 struct lisp_time *result, double *dresult)
838{ 824{
839 Lisp_Object high = make_fixnum (0); 825 Lisp_Object high = make_fixnum (0);
@@ -854,7 +840,7 @@ decode_lisp_time (Lisp_Object specified_time, int flags,
854 { 840 {
855 Lisp_Object low_tail = XCDR (low); 841 Lisp_Object low_tail = XCDR (low);
856 low = XCAR (low); 842 low = XCAR (low);
857 if (! (flags & DECODE_SECS_ONLY)) 843 if (! decode_secs_only)
858 { 844 {
859 if (CONSP (low_tail)) 845 if (CONSP (low_tail))
860 { 846 {
@@ -877,9 +863,6 @@ decode_lisp_time (Lisp_Object specified_time, int flags,
877 } 863 }
878 else 864 else
879 { 865 {
880 if (flags & WARN_OBSOLETE_TIMESTAMPS
881 && RANGED_FIXNUMP (0, low, (1 << LO_TIME_BITS) - 1))
882 message ("obsolete timestamp with cdr %"pI"d", XFIXNUM (low));
883 form = TIMEFORM_TICKS_HZ; 866 form = TIMEFORM_TICKS_HZ;
884 } 867 }
885 868
@@ -1008,8 +991,7 @@ static struct lisp_time
1008lisp_time_struct (Lisp_Object specified_time, enum timeform *pform) 991lisp_time_struct (Lisp_Object specified_time, enum timeform *pform)
1009{ 992{
1010 struct lisp_time t; 993 struct lisp_time t;
1011 enum timeform form 994 enum timeform form = decode_lisp_time (specified_time, false, &t, 0);
1012 = decode_lisp_time (specified_time, WARN_OBSOLETE_TIMESTAMPS, &t, 0);
1013 if (pform) 995 if (pform)
1014 *pform = form; 996 *pform = form;
1015 return t; 997 return t;
@@ -1034,9 +1016,8 @@ lisp_time_argument (Lisp_Object specified_time)
1034static time_t 1016static time_t
1035lisp_seconds_argument (Lisp_Object specified_time) 1017lisp_seconds_argument (Lisp_Object specified_time)
1036{ 1018{
1037 int flags = WARN_OBSOLETE_TIMESTAMPS | DECODE_SECS_ONLY;
1038 struct lisp_time lt; 1019 struct lisp_time lt;
1039 decode_lisp_time (specified_time, flags, &lt, 0); 1020 decode_lisp_time (specified_time, true, &lt, 0);
1040 struct timespec t = lisp_to_timespec (lt); 1021 struct timespec t = lisp_to_timespec (lt);
1041 if (! timespec_valid_p (t)) 1022 if (! timespec_valid_p (t))
1042 time_overflow (); 1023 time_overflow ();
@@ -1138,24 +1119,6 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1138 mpz_t *ihz = &mpz[0]; 1119 mpz_t *ihz = &mpz[0];
1139 mpz_mul (*ihz, *fa, *db); 1120 mpz_mul (*ihz, *fa, *db);
1140 1121
1141 /* When warning about obsolete timestamps, if the smaller
1142 denominator comes from a non-(TICKS . HZ) timestamp and could
1143 generate a (TICKS . HZ) timestamp that would look obsolete,
1144 arrange for the result to have a higher HZ to avoid a
1145 spurious warning by a later consumer of this function's
1146 returned value. */
1147 verify (1 << LO_TIME_BITS <= ULONG_MAX);
1148 if (WARN_OBSOLETE_TIMESTAMPS
1149 && (da_lt_db ? aform : bform) == TIMEFORM_FLOAT
1150 && (da_lt_db ? bform : aform) != TIMEFORM_TICKS_HZ
1151 && mpz_cmp_ui (*hzmin, 1) > 0
1152 && mpz_cmp_ui (*hzmin, 1 << LO_TIME_BITS) < 0)
1153 {
1154 mpz_t *hzmin1 = &mpz[2 - da_lt_db];
1155 mpz_set_ui (*hzmin1, 1 << LO_TIME_BITS);
1156 hzmin = hzmin1;
1157 }
1158
1159 /* iticks = (fb * na) OP (fa * nb), where OP is + or -. */ 1122 /* iticks = (fb * na) OP (fa * nb), where OP is + or -. */
1160 mpz_t const *na = bignum_integer (iticks, ta.ticks); 1123 mpz_t const *na = bignum_integer (iticks, ta.ticks);
1161 mpz_mul (*iticks, *fb, *na); 1124 mpz_mul (*iticks, *fb, *na);
@@ -1177,8 +1140,7 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1177 upwards by multiplying the normalized numerator and denominator 1140 upwards by multiplying the normalized numerator and denominator
1178 so that the resulting denominator becomes at least hzmin. 1141 so that the resulting denominator becomes at least hzmin.
1179 This rescaling avoids returning a timestamp that is less precise 1142 This rescaling avoids returning a timestamp that is less precise
1180 than both a and b, or a timestamp that looks obsolete when that 1143 than both a and b. */
1181 might be a problem. */
1182 if (!FASTER_TIMEFNS || mpz_cmp (*ihz, *hzmin) < 0) 1144 if (!FASTER_TIMEFNS || mpz_cmp (*ihz, *hzmin) < 0)
1183 { 1145 {
1184 /* Rescale straightforwardly. Although this might not 1146 /* Rescale straightforwardly. Although this might not
@@ -1303,7 +1265,7 @@ or (if you need time as a string) `format-time-string'. */)
1303 (Lisp_Object specified_time) 1265 (Lisp_Object specified_time)
1304{ 1266{
1305 double t; 1267 double t;
1306 decode_lisp_time (specified_time, 0, 0, &t); 1268 decode_lisp_time (specified_time, false, 0, &t);
1307 return make_float (t); 1269 return make_float (t);
1308} 1270}
1309 1271
@@ -1651,12 +1613,11 @@ saving flag to be guessed.
1651 1613
1652As an obsolescent calling convention, if this function is called with 1614As an obsolescent calling convention, if this function is called with
16536 or more arguments, the first 6 arguments are SECOND, MINUTE, HOUR, 16156 or more arguments, the first 6 arguments are SECOND, MINUTE, HOUR,
1654DAY, MONTH, and YEAR, and specify the components of a decoded time, 1616DAY, MONTH, and YEAR, and specify the components of a decoded time.
1655where DST assumed to be -1 and FORM is omitted. If there are more 1617If there are more than 6 arguments the *last* argument is used as ZONE
1656than 6 arguments the *last* argument is used as ZONE and any other 1618and any other extra arguments are ignored, so that (apply
1657extra arguments are ignored, so that (apply #\\='encode-time 1619#\\='encode-time (decode-time ...)) works. In this obsolescent
1658(decode-time ...)) works. In this obsolescent convention, DST and 1620convention, DST and ZONE default to -1 and nil respectively.
1659ZONE default to -1 and nil respectively.
1660 1621
1661Years before 1970 are not guaranteed to work. On some systems, 1622Years before 1970 are not guaranteed to work. On some systems,
1662year values as low as 1901 do work. 1623year values as low as 1901 do work.
@@ -1703,7 +1664,7 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */)
1703 1664
1704 /* Let SEC = floor (LT.ticks / HZ), with SUBSECTICKS the remainder. */ 1665 /* Let SEC = floor (LT.ticks / HZ), with SUBSECTICKS the remainder. */
1705 struct lisp_time lt; 1666 struct lisp_time lt;
1706 decode_lisp_time (secarg, 0, &lt, 0); 1667 decode_lisp_time (secarg, false, &lt, 0);
1707 Lisp_Object hz = lt.hz, sec, subsecticks; 1668 Lisp_Object hz = lt.hz, sec, subsecticks;
1708 if (FASTER_TIMEFNS && EQ (hz, make_fixnum (1))) 1669 if (FASTER_TIMEFNS && EQ (hz, make_fixnum (1)))
1709 { 1670 {
@@ -1756,9 +1717,7 @@ Truncate the returned value toward minus infinity.
1756If FORM is nil (the default), return the same form as `current-time'. 1717If FORM is nil (the default), return the same form as `current-time'.
1757If FORM is a positive integer, return a pair of integers (TICKS . FORM), 1718If FORM is a positive integer, return a pair of integers (TICKS . FORM),
1758where TICKS is the number of clock ticks and FORM is the clock frequency 1719where TICKS is the number of clock ticks and FORM is the clock frequency
1759in ticks per second. (Currently the positive integer should be at least 1720in ticks per second. If FORM is t, return (TICKS . PHZ), where
176065536 if the returned value is expected to be given to standard functions
1761expecting Lisp timestamps.) If FORM is t, return (TICKS . PHZ), where
1762PHZ is a suitable clock frequency in ticks per second. If FORM is 1721PHZ is a suitable clock frequency in ticks per second. If FORM is
1763`integer', return an integer count of seconds. If FORM is `list', 1722`integer', return an integer count of seconds. If FORM is `list',
1764return an integer list (HIGH LOW USEC PSEC), where HIGH has the most 1723return an integer list (HIGH LOW USEC PSEC), where HIGH has the most
@@ -1767,7 +1726,7 @@ bits, and USEC and PSEC are the microsecond and picosecond counts. */)
1767 (Lisp_Object time, Lisp_Object form) 1726 (Lisp_Object time, Lisp_Object form)
1768{ 1727{
1769 struct lisp_time t; 1728 struct lisp_time t;
1770 enum timeform input_form = decode_lisp_time (time, 0, &t, 0); 1729 enum timeform input_form = decode_lisp_time (time, false, &t, 0);
1771 if (NILP (form)) 1730 if (NILP (form))
1772 form = CURRENT_TIME_LIST ? Qlist : Qt; 1731 form = CURRENT_TIME_LIST ? Qlist : Qt;
1773 if (EQ (form, Qlist)) 1732 if (EQ (form, Qlist))
diff --git a/src/xfns.c b/src/xfns.c
index b5694829aef..dc25d7bfca2 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -2916,7 +2916,7 @@ initial_set_up_x_back_buffer (struct frame *f)
2916 unblock_input (); 2916 unblock_input ();
2917} 2917}
2918 2918
2919#if defined HAVE_XINPUT2 && !defined USE_GTK 2919#if defined HAVE_XINPUT2
2920static void 2920static void
2921setup_xi_event_mask (struct frame *f) 2921setup_xi_event_mask (struct frame *f)
2922{ 2922{
@@ -2927,6 +2927,9 @@ setup_xi_event_mask (struct frame *f)
2927 mask.mask = m = alloca (l); 2927 mask.mask = m = alloca (l);
2928 memset (m, 0, l); 2928 memset (m, 0, l);
2929 mask.mask_len = l; 2929 mask.mask_len = l;
2930
2931 block_input ();
2932#ifndef USE_GTK
2930 mask.deviceid = XIAllMasterDevices; 2933 mask.deviceid = XIAllMasterDevices;
2931 2934
2932 XISetMask (m, XI_ButtonPress); 2935 XISetMask (m, XI_ButtonPress);
@@ -2945,14 +2948,25 @@ setup_xi_event_mask (struct frame *f)
2945 &mask, 1); 2948 &mask, 1);
2946 2949
2947 memset (m, 0, l); 2950 memset (m, 0, l);
2951#endif /* !USE_GTK */
2952
2948 mask.deviceid = XIAllDevices; 2953 mask.deviceid = XIAllDevices;
2949 2954
2950 XISetMask (m, XI_PropertyEvent); 2955 XISetMask (m, XI_PropertyEvent);
2951 XISetMask (m, XI_HierarchyChanged); 2956 XISetMask (m, XI_HierarchyChanged);
2952 XISetMask (m, XI_DeviceChanged); 2957 XISetMask (m, XI_DeviceChanged);
2958#ifdef XI_TouchBegin
2959 if (FRAME_DISPLAY_INFO (f)->xi2_version >= 2)
2960 {
2961 XISetMask (m, XI_TouchBegin);
2962 XISetMask (m, XI_TouchUpdate);
2963 XISetMask (m, XI_TouchEnd);
2964 }
2965#endif
2953 XISelectEvents (FRAME_X_DISPLAY (f), 2966 XISelectEvents (FRAME_X_DISPLAY (f),
2954 FRAME_X_WINDOW (f), 2967 FRAME_X_WINDOW (f),
2955 &mask, 1); 2968 &mask, 1);
2969 unblock_input ();
2956} 2970}
2957#endif 2971#endif
2958 2972
@@ -3249,6 +3263,11 @@ x_window (struct frame *f)
3249 unblock_input (); 3263 unblock_input ();
3250 } 3264 }
3251#endif 3265#endif
3266
3267#ifdef HAVE_XINPUT2
3268 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
3269 setup_xi_event_mask (f);
3270#endif
3252} 3271}
3253 3272
3254#else /*! USE_GTK */ 3273#else /*! USE_GTK */
diff --git a/src/xterm.c b/src/xterm.c
index 646985bdc20..fa60a4e8745 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -353,6 +353,8 @@ x_extension_initialize (struct x_display_info *dpyinfo)
353static void 353static void
354x_free_xi_devices (struct x_display_info *dpyinfo) 354x_free_xi_devices (struct x_display_info *dpyinfo)
355{ 355{
356 struct xi_touch_point_t *tem, *last;
357
356 block_input (); 358 block_input ();
357 359
358 if (dpyinfo->num_devices) 360 if (dpyinfo->num_devices)
@@ -362,6 +364,14 @@ x_free_xi_devices (struct x_display_info *dpyinfo)
362 XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id, 364 XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id,
363 CurrentTime); 365 CurrentTime);
364 xfree (dpyinfo->devices[i].valuators); 366 xfree (dpyinfo->devices[i].valuators);
367
368 tem = dpyinfo->devices[i].touchpoints;
369 while (tem)
370 {
371 last = tem;
372 tem = tem->next;
373 xfree (last);
374 }
365 } 375 }
366 376
367 xfree (dpyinfo->devices); 377 xfree (dpyinfo->devices);
@@ -407,7 +417,7 @@ x_init_master_valuators (struct x_display_info *dpyinfo)
407 block_input (); 417 block_input ();
408 x_free_xi_devices (dpyinfo); 418 x_free_xi_devices (dpyinfo);
409 infos = XIQueryDevice (dpyinfo->display, 419 infos = XIQueryDevice (dpyinfo->display,
410 XIAllMasterDevices, 420 XIAllDevices,
411 &ndevices); 421 &ndevices);
412 422
413 if (!ndevices) 423 if (!ndevices)
@@ -432,6 +442,10 @@ x_init_master_valuators (struct x_display_info *dpyinfo)
432 xi_device->grab = 0; 442 xi_device->grab = 0;
433 xi_device->valuators = 443 xi_device->valuators =
434 xmalloc (sizeof *xi_device->valuators * device->num_classes); 444 xmalloc (sizeof *xi_device->valuators * device->num_classes);
445 xi_device->touchpoints = NULL;
446 xi_device->master_p = (device->use == XIMasterKeyboard
447 || device->use == XIMasterPointer);
448 xi_device->direct_p = false;
435 449
436 for (int c = 0; c < device->num_classes; ++c) 450 for (int c = 0; c < device->num_classes; ++c)
437 { 451 {
@@ -442,22 +456,36 @@ x_init_master_valuators (struct x_display_info *dpyinfo)
442 { 456 {
443 XIScrollClassInfo *info = 457 XIScrollClassInfo *info =
444 (XIScrollClassInfo *) device->classes[c]; 458 (XIScrollClassInfo *) device->classes[c];
445 struct xi_scroll_valuator_t *valuator = 459 struct xi_scroll_valuator_t *valuator;
446 &xi_device->valuators[actual_valuator_count++]; 460
447 461 if (xi_device->master_p)
448 valuator->horizontal 462 {
449 = (info->scroll_type == XIScrollTypeHorizontal); 463 valuator = &xi_device->valuators[actual_valuator_count++];
450 valuator->invalid_p = true; 464 valuator->horizontal
451 valuator->emacs_value = DBL_MIN; 465 = (info->scroll_type == XIScrollTypeHorizontal);
452 valuator->increment = info->increment; 466 valuator->invalid_p = true;
453 valuator->number = info->number; 467 valuator->emacs_value = DBL_MIN;
468 valuator->increment = info->increment;
469 valuator->number = info->number;
470 }
471
454 break; 472 break;
455 } 473 }
456#endif 474#endif
475#ifdef XITouchClass /* XInput 2.2 */
476 case XITouchClass:
477 {
478 XITouchClassInfo *info;
479
480 info = (XITouchClassInfo *) device->classes[c];
481 xi_device->direct_p = info->mode == XIDirectTouch;
482 }
483#endif
457 default: 484 default:
458 break; 485 break;
459 } 486 }
460 } 487 }
488
461 xi_device->scroll_valuator_count = actual_valuator_count; 489 xi_device->scroll_valuator_count = actual_valuator_count;
462 } 490 }
463 } 491 }
@@ -484,7 +512,7 @@ x_get_scroll_valuator_delta (struct x_display_info *dpyinfo, int device_id,
484 { 512 {
485 struct xi_device_t *device = &dpyinfo->devices[i]; 513 struct xi_device_t *device = &dpyinfo->devices[i];
486 514
487 if (device->device_id == device_id) 515 if (device->device_id == device_id && device->master_p)
488 { 516 {
489 for (int j = 0; j < device->scroll_valuator_count; ++j) 517 for (int j = 0; j < device->scroll_valuator_count; ++j)
490 { 518 {
@@ -534,6 +562,61 @@ xi_device_from_id (struct x_display_info *dpyinfo, int deviceid)
534 return NULL; 562 return NULL;
535} 563}
536 564
565#ifdef XI_TouchBegin
566
567static void
568xi_link_touch_point (struct xi_device_t *device,
569 int detail, double x, double y)
570{
571 struct xi_touch_point_t *touchpoint;
572
573 touchpoint = xmalloc (sizeof *touchpoint);
574 touchpoint->next = device->touchpoints;
575 touchpoint->x = x;
576 touchpoint->y = y;
577 touchpoint->number = detail;
578
579 device->touchpoints = touchpoint;
580}
581
582static void
583xi_unlink_touch_point (int detail,
584 struct xi_device_t *device)
585{
586 struct xi_touch_point_t *last, *tem;
587
588 for (last = NULL, tem = device->touchpoints; tem;
589 last = tem, tem = tem->next)
590 {
591 if (tem->number == detail)
592 {
593 if (!last)
594 device->touchpoints = tem->next;
595 else
596 last->next = tem->next;
597
598 xfree (tem);
599 return;
600 }
601 }
602}
603
604static struct xi_touch_point_t *
605xi_find_touch_point (struct xi_device_t *device, int detail)
606{
607 struct xi_touch_point_t *point;
608
609 for (point = device->touchpoints; point; point = point->next)
610 {
611 if (point->number == detail)
612 return point;
613 }
614
615 return NULL;
616}
617
618#endif /* XI_TouchBegin */
619
537static void 620static void
538xi_grab_or_ungrab_device (struct xi_device_t *device, 621xi_grab_or_ungrab_device (struct xi_device_t *device,
539 struct x_display_info *dpyinfo, 622 struct x_display_info *dpyinfo,
@@ -570,7 +653,7 @@ xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo, int id)
570 struct xi_device_t *device = xi_device_from_id (dpyinfo, id); 653 struct xi_device_t *device = xi_device_from_id (dpyinfo, id);
571 struct xi_scroll_valuator_t *valuator; 654 struct xi_scroll_valuator_t *valuator;
572 655
573 if (!device) 656 if (!device || !device->master_p)
574 return; 657 return;
575 658
576 if (!device->scroll_valuator_count) 659 if (!device->scroll_valuator_count)
@@ -9981,242 +10064,250 @@ handle_one_xevent (struct x_display_info *dpyinfo,
9981#endif 10064#endif
9982 goto XI_OTHER; 10065 goto XI_OTHER;
9983 case XI_Motion: 10066 case XI_Motion:
9984 states = &xev->valuators; 10067 {
9985 values = states->values; 10068 struct xi_device_t *device;
9986 10069
9987 x_display_set_last_user_time (dpyinfo, xi_event->time); 10070 states = &xev->valuators;
10071 values = states->values;
10072 device = xi_device_from_id (dpyinfo, xev->deviceid);
10073
10074 if (!device || !device->master_p)
10075 goto XI_OTHER;
10076
10077 x_display_set_last_user_time (dpyinfo, xi_event->time);
9988 10078
9989#ifdef HAVE_XWIDGETS 10079#ifdef HAVE_XWIDGETS
9990 struct xwidget_view *xv = xwidget_view_from_window (xev->event); 10080 struct xwidget_view *xv = xwidget_view_from_window (xev->event);
9991 double xv_total_x = 0.0; 10081 double xv_total_x = 0.0;
9992 double xv_total_y = 0.0; 10082 double xv_total_y = 0.0;
9993#endif 10083#endif
9994 10084
9995 for (int i = 0; i < states->mask_len * 8; i++) 10085 for (int i = 0; i < states->mask_len * 8; i++)
9996 { 10086 {
9997 if (XIMaskIsSet (states->mask, i)) 10087 if (XIMaskIsSet (states->mask, i))
9998 { 10088 {
9999 struct xi_scroll_valuator_t *val; 10089 struct xi_scroll_valuator_t *val;
10000 double delta, scroll_unit; 10090 double delta, scroll_unit;
10001 int scroll_height; 10091 int scroll_height;
10002 Lisp_Object window; 10092 Lisp_Object window;
10003 10093
10004 10094
10005 /* See the comment on top of 10095 /* See the comment on top of
10006 x_init_master_valuators for more details on how 10096 x_init_master_valuators for more details on how
10007 scroll wheel movement is reported on XInput 2. */ 10097 scroll wheel movement is reported on XInput 2. */
10008 delta = x_get_scroll_valuator_delta (dpyinfo, xev->deviceid, 10098 delta = x_get_scroll_valuator_delta (dpyinfo, xev->deviceid,
10009 i, *values, &val); 10099 i, *values, &val);
10010 10100
10011 if (delta != DBL_MAX) 10101 if (delta != DBL_MAX)
10012 { 10102 {
10013#ifdef HAVE_XWIDGETS 10103#ifdef HAVE_XWIDGETS
10014 if (xv) 10104 if (xv)
10015 { 10105 {
10016 if (val->horizontal) 10106 if (val->horizontal)
10017 xv_total_x += delta; 10107 xv_total_x += delta;
10018 else 10108 else
10019 xv_total_y += delta; 10109 xv_total_y += delta;
10020 10110
10021 found_valuator = true; 10111 found_valuator = true;
10022 10112
10023 if (delta == 0.0) 10113 if (delta == 0.0)
10024 any_stop_p = true; 10114 any_stop_p = true;
10025 10115
10026 continue; 10116 continue;
10027 } 10117 }
10028#endif 10118#endif
10029 if (!f) 10119 if (!f)
10030 { 10120 {
10031 f = x_any_window_to_frame (dpyinfo, xev->event); 10121 f = x_any_window_to_frame (dpyinfo, xev->event);
10032 10122
10033 if (!f) 10123 if (!f)
10034 goto XI_OTHER; 10124 goto XI_OTHER;
10035 } 10125 }
10036 10126
10037 found_valuator = true; 10127 found_valuator = true;
10038 10128
10039 if (signbit (delta) != signbit (val->emacs_value)) 10129 if (signbit (delta) != signbit (val->emacs_value))
10040 val->emacs_value = 0; 10130 val->emacs_value = 0;
10041 10131
10042 val->emacs_value += delta; 10132 val->emacs_value += delta;
10043 10133
10044 if (mwheel_coalesce_scroll_events 10134 if (mwheel_coalesce_scroll_events
10045 && (fabs (val->emacs_value) < 1) 10135 && (fabs (val->emacs_value) < 1)
10046 && (fabs (delta) > 0)) 10136 && (fabs (delta) > 0))
10047 continue; 10137 continue;
10048 10138
10049 bool s = signbit (val->emacs_value); 10139 bool s = signbit (val->emacs_value);
10050 inev.ie.kind = (fabs (delta) > 0 10140 inev.ie.kind = (fabs (delta) > 0
10051 ? (val->horizontal 10141 ? (val->horizontal
10052 ? HORIZ_WHEEL_EVENT 10142 ? HORIZ_WHEEL_EVENT
10053 : WHEEL_EVENT) 10143 : WHEEL_EVENT)
10054 : TOUCH_END_EVENT); 10144 : TOUCH_END_EVENT);
10055 inev.ie.timestamp = xev->time; 10145 inev.ie.timestamp = xev->time;
10056 10146
10057 XSETINT (inev.ie.x, lrint (xev->event_x)); 10147 XSETINT (inev.ie.x, lrint (xev->event_x));
10058 XSETINT (inev.ie.y, lrint (xev->event_y)); 10148 XSETINT (inev.ie.y, lrint (xev->event_y));
10059 XSETFRAME (inev.ie.frame_or_window, f); 10149 XSETFRAME (inev.ie.frame_or_window, f);
10060 10150
10061 if (fabs (delta) > 0) 10151 if (fabs (delta) > 0)
10062 { 10152 {
10063 inev.ie.modifiers = !s ? up_modifier : down_modifier; 10153 inev.ie.modifiers = !s ? up_modifier : down_modifier;
10064 inev.ie.modifiers 10154 inev.ie.modifiers
10065 |= x_x_to_emacs_modifiers (dpyinfo, 10155 |= x_x_to_emacs_modifiers (dpyinfo,
10066 xev->mods.effective); 10156 xev->mods.effective);
10067 } 10157 }
10068 10158
10069 window = window_from_coordinates (f, xev->event_x, 10159 window = window_from_coordinates (f, xev->event_x,
10070 xev->event_y, NULL, 10160 xev->event_y, NULL,
10071 false, false); 10161 false, false);
10072 10162
10073 if (WINDOWP (window)) 10163 if (WINDOWP (window))
10074 scroll_height = XWINDOW (window)->pixel_height; 10164 scroll_height = XWINDOW (window)->pixel_height;
10075 else 10165 else
10076 /* EVENT_X and EVENT_Y can be outside the 10166 /* EVENT_X and EVENT_Y can be outside the
10077 frame if F holds the input grab, so fall 10167 frame if F holds the input grab, so fall
10078 back to the height of the frame instead. */ 10168 back to the height of the frame instead. */
10079 scroll_height = FRAME_PIXEL_HEIGHT (f); 10169 scroll_height = FRAME_PIXEL_HEIGHT (f);
10080 10170
10081 scroll_unit = pow (scroll_height, 2.0 / 3.0); 10171 scroll_unit = pow (scroll_height, 2.0 / 3.0);
10082 10172
10083 if (NUMBERP (Vx_scroll_event_delta_factor)) 10173 if (NUMBERP (Vx_scroll_event_delta_factor))
10084 scroll_unit *= XFLOATINT (Vx_scroll_event_delta_factor); 10174 scroll_unit *= XFLOATINT (Vx_scroll_event_delta_factor);
10085 10175
10086 if (fabs (delta) > 0) 10176 if (fabs (delta) > 0)
10087 { 10177 {
10088 if (val->horizontal) 10178 if (val->horizontal)
10089 { 10179 {
10090 inev.ie.arg 10180 inev.ie.arg
10091 = list3 (Qnil, 10181 = list3 (Qnil,
10092 make_float (val->emacs_value 10182 make_float (val->emacs_value
10093 * scroll_unit), 10183 * scroll_unit),
10094 make_float (0)); 10184 make_float (0));
10095 } 10185 }
10096 else 10186 else
10097 { 10187 {
10098 inev.ie.arg = list3 (Qnil, make_float (0), 10188 inev.ie.arg = list3 (Qnil, make_float (0),
10099 make_float (val->emacs_value 10189 make_float (val->emacs_value
10100 * scroll_unit)); 10190 * scroll_unit));
10101 } 10191 }
10102 } 10192 }
10103 else 10193 else
10104 { 10194 {
10105 inev.ie.arg = Qnil; 10195 inev.ie.arg = Qnil;
10106 } 10196 }
10107 10197
10108 kbd_buffer_store_event_hold (&inev.ie, hold_quit); 10198 kbd_buffer_store_event_hold (&inev.ie, hold_quit);
10109 10199
10110 val->emacs_value = 0; 10200 val->emacs_value = 0;
10111 } 10201 }
10112 values++; 10202 values++;
10113 } 10203 }
10114 10204
10115 inev.ie.kind = NO_EVENT; 10205 inev.ie.kind = NO_EVENT;
10116 } 10206 }
10117 10207
10118#ifdef HAVE_XWIDGETS 10208#ifdef HAVE_XWIDGETS
10119 if (xv) 10209 if (xv)
10120 { 10210 {
10121 if (found_valuator) 10211 if (found_valuator)
10122 xwidget_scroll (xv, xev->event_x, xev->event_y, 10212 xwidget_scroll (xv, xev->event_x, xev->event_y,
10123 xv_total_x, xv_total_y, xev->mods.effective, 10213 xv_total_x, xv_total_y, xev->mods.effective,
10124 xev->time, any_stop_p); 10214 xev->time, any_stop_p);
10125 else 10215 else
10126 xwidget_motion_notify (xv, xev->event_x, xev->event_y, 10216 xwidget_motion_notify (xv, xev->event_x, xev->event_y,
10127 xev->mods.effective, xev->time); 10217 xev->mods.effective, xev->time);
10128 10218
10129 goto XI_OTHER; 10219 goto XI_OTHER;
10130 } 10220 }
10131#endif 10221#endif
10132 if (found_valuator) 10222 if (found_valuator)
10133 goto XI_OTHER; 10223 goto XI_OTHER;
10134 10224
10135 ev.x = lrint (xev->event_x); 10225 ev.x = lrint (xev->event_x);
10136 ev.y = lrint (xev->event_y); 10226 ev.y = lrint (xev->event_y);
10137 ev.window = xev->event; 10227 ev.window = xev->event;
10138 ev.time = xev->time; 10228 ev.time = xev->time;
10139 10229
10140 previous_help_echo_string = help_echo_string; 10230 previous_help_echo_string = help_echo_string;
10141 help_echo_string = Qnil; 10231 help_echo_string = Qnil;
10142 10232
10143 if (hlinfo->mouse_face_hidden) 10233 if (hlinfo->mouse_face_hidden)
10144 { 10234 {
10145 hlinfo->mouse_face_hidden = false; 10235 hlinfo->mouse_face_hidden = false;
10146 clear_mouse_face (hlinfo); 10236 clear_mouse_face (hlinfo);
10147 } 10237 }
10148 10238
10149 f = mouse_or_wdesc_frame (dpyinfo, xev->event); 10239 f = mouse_or_wdesc_frame (dpyinfo, xev->event);
10150 10240
10151#ifdef USE_GTK 10241#ifdef USE_GTK
10152 if (f && xg_event_is_for_scrollbar (f, event)) 10242 if (f && xg_event_is_for_scrollbar (f, event))
10153 f = 0; 10243 f = 0;
10154#endif 10244#endif
10155 if (f) 10245 if (f)
10156 { 10246 {
10157 /* Maybe generate a SELECT_WINDOW_EVENT for 10247 /* Maybe generate a SELECT_WINDOW_EVENT for
10158 `mouse-autoselect-window' but don't let popup menus 10248 `mouse-autoselect-window' but don't let popup menus
10159 interfere with this (Bug#1261). */ 10249 interfere with this (Bug#1261). */
10160 if (!NILP (Vmouse_autoselect_window) 10250 if (!NILP (Vmouse_autoselect_window)
10161 && !popup_activated () 10251 && !popup_activated ()
10162 /* Don't switch if we're currently in the minibuffer. 10252 /* Don't switch if we're currently in the minibuffer.
10163 This tries to work around problems where the 10253 This tries to work around problems where the
10164 minibuffer gets unselected unexpectedly, and where 10254 minibuffer gets unselected unexpectedly, and where
10165 you then have to move your mouse all the way down to 10255 you then have to move your mouse all the way down to
10166 the minibuffer to select it. */ 10256 the minibuffer to select it. */
10167 && !MINI_WINDOW_P (XWINDOW (selected_window)) 10257 && !MINI_WINDOW_P (XWINDOW (selected_window))
10168 /* With `focus-follows-mouse' non-nil create an event 10258 /* With `focus-follows-mouse' non-nil create an event
10169 also when the target window is on another frame. */ 10259 also when the target window is on another frame. */
10170 && (f == XFRAME (selected_frame) 10260 && (f == XFRAME (selected_frame)
10171 || !NILP (focus_follows_mouse))) 10261 || !NILP (focus_follows_mouse)))
10172 { 10262 {
10173 static Lisp_Object last_mouse_window; 10263 static Lisp_Object last_mouse_window;
10174 Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false); 10264 Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false);
10175 10265
10176 /* A window will be autoselected only when it is not 10266 /* A window will be autoselected only when it is not
10177 selected now and the last mouse movement event was 10267 selected now and the last mouse movement event was
10178 not in it. The remainder of the code is a bit vague 10268 not in it. The remainder of the code is a bit vague
10179 wrt what a "window" is. For immediate autoselection, 10269 wrt what a "window" is. For immediate autoselection,
10180 the window is usually the entire window but for GTK 10270 the window is usually the entire window but for GTK
10181 where the scroll bars don't count. For delayed 10271 where the scroll bars don't count. For delayed
10182 autoselection the window is usually the window's text 10272 autoselection the window is usually the window's text
10183 area including the margins. */ 10273 area including the margins. */
10184 if (WINDOWP (window) 10274 if (WINDOWP (window)
10185 && !EQ (window, last_mouse_window) 10275 && !EQ (window, last_mouse_window)
10186 && !EQ (window, selected_window)) 10276 && !EQ (window, selected_window))
10187 { 10277 {
10188 inev.ie.kind = SELECT_WINDOW_EVENT; 10278 inev.ie.kind = SELECT_WINDOW_EVENT;
10189 inev.ie.frame_or_window = window; 10279 inev.ie.frame_or_window = window;
10190 } 10280 }
10191 10281
10192 /* Remember the last window where we saw the mouse. */ 10282 /* Remember the last window where we saw the mouse. */
10193 last_mouse_window = window; 10283 last_mouse_window = window;
10194 } 10284 }
10195 10285
10196 if (!x_note_mouse_movement (f, &ev)) 10286 if (!x_note_mouse_movement (f, &ev))
10197 help_echo_string = previous_help_echo_string; 10287 help_echo_string = previous_help_echo_string;
10198 } 10288 }
10199 else 10289 else
10200 { 10290 {
10201#ifndef USE_TOOLKIT_SCROLL_BARS 10291#ifndef USE_TOOLKIT_SCROLL_BARS
10202 struct scroll_bar *bar 10292 struct scroll_bar *bar
10203 = x_window_to_scroll_bar (xi_event->display, xev->event, 2); 10293 = x_window_to_scroll_bar (xi_event->display, xev->event, 2);
10204 10294
10205 if (bar) 10295 if (bar)
10206 x_scroll_bar_note_movement (bar, &ev); 10296 x_scroll_bar_note_movement (bar, &ev);
10207#endif /* USE_TOOLKIT_SCROLL_BARS */ 10297#endif /* USE_TOOLKIT_SCROLL_BARS */
10208 10298
10209 /* If we move outside the frame, then we're 10299 /* If we move outside the frame, then we're
10210 certainly no longer on any text in the frame. */ 10300 certainly no longer on any text in the frame. */
10211 clear_mouse_face (hlinfo); 10301 clear_mouse_face (hlinfo);
10212 } 10302 }
10213 10303
10214 /* If the contents of the global variable help_echo_string 10304 /* If the contents of the global variable help_echo_string
10215 has changed, generate a HELP_EVENT. */ 10305 has changed, generate a HELP_EVENT. */
10216 if (!NILP (help_echo_string) 10306 if (!NILP (help_echo_string)
10217 || !NILP (previous_help_echo_string)) 10307 || !NILP (previous_help_echo_string))
10218 do_help = 1; 10308 do_help = 1;
10219 goto XI_OTHER; 10309 goto XI_OTHER;
10310 }
10220 case XI_ButtonRelease: 10311 case XI_ButtonRelease:
10221 case XI_ButtonPress: 10312 case XI_ButtonPress:
10222 { 10313 {
@@ -10242,6 +10333,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
10242 10333
10243 device = xi_device_from_id (dpyinfo, xev->deviceid); 10334 device = xi_device_from_id (dpyinfo, xev->deviceid);
10244 10335
10336 if (!device || !device->master_p)
10337 goto XI_OTHER;
10338
10245 bv.button = xev->detail; 10339 bv.button = xev->detail;
10246 bv.type = xev->evtype == XI_ButtonPress ? ButtonPress : ButtonRelease; 10340 bv.type = xev->evtype == XI_ButtonPress ? ButtonPress : ButtonRelease;
10247 bv.x = lrint (xev->event_x); 10341 bv.x = lrint (xev->event_x);
@@ -10408,6 +10502,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
10408 int copy_bufsiz = sizeof (copy_buffer); 10502 int copy_bufsiz = sizeof (copy_buffer);
10409 ptrdiff_t i; 10503 ptrdiff_t i;
10410 int nchars, len; 10504 int nchars, len;
10505 struct xi_device_t *device;
10506
10507 device = xi_device_from_id (dpyinfo, xev->deviceid);
10508
10509 if (!device || !device->master_p)
10510 goto XI_OTHER;
10411 10511
10412#if defined (USE_X_TOOLKIT) || defined (USE_GTK) 10512#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
10413 /* Dispatch XI_KeyPress events when in menu. */ 10513 /* Dispatch XI_KeyPress events when in menu. */
@@ -10765,6 +10865,108 @@ handle_one_xevent (struct x_display_info *dpyinfo,
10765 case XI_DeviceChanged: 10865 case XI_DeviceChanged:
10766 x_init_master_valuators (dpyinfo); 10866 x_init_master_valuators (dpyinfo);
10767 goto XI_OTHER; 10867 goto XI_OTHER;
10868#ifdef XI_TouchBegin
10869 case XI_TouchBegin:
10870 {
10871 struct xi_device_t *device;
10872 device = xi_device_from_id (dpyinfo, xev->deviceid);
10873
10874 if (!device)
10875 goto XI_OTHER;
10876
10877 if (xi_find_touch_point (device, xev->detail))
10878 emacs_abort ();
10879
10880 f = x_any_window_to_frame (dpyinfo, xev->event);
10881
10882 if (f && device->direct_p)
10883 {
10884 xi_link_touch_point (device, xev->detail, xev->event_x,
10885 xev->event_y);
10886
10887 inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
10888 inev.ie.timestamp = xev->time;
10889 XSETFRAME (inev.ie.frame_or_window, f);
10890 XSETINT (inev.ie.x, lrint (xev->event_x));
10891 XSETINT (inev.ie.y, lrint (xev->event_y));
10892 XSETINT (inev.ie.arg, xev->detail);
10893
10894 XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
10895 xev->detail, xev->event, XIAcceptTouch);
10896 }
10897 else
10898 XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
10899 xev->detail, xev->event, XIRejectTouch);
10900
10901 goto XI_OTHER;
10902 }
10903 case XI_TouchUpdate:
10904 {
10905 struct xi_device_t *device;
10906 struct xi_touch_point_t *touchpoint;
10907 Lisp_Object arg = Qnil;
10908
10909 device = xi_device_from_id (dpyinfo, xev->deviceid);
10910
10911 if (!device)
10912 goto XI_OTHER;
10913
10914 touchpoint = xi_find_touch_point (device, xev->detail);
10915
10916 if (!touchpoint)
10917 emacs_abort ();
10918
10919 touchpoint->x = xev->event_x;
10920 touchpoint->y = xev->event_y;
10921
10922 f = x_any_window_to_frame (dpyinfo, xev->event);
10923
10924 if (f && device->direct_p)
10925 {
10926 inev.ie.kind = TOUCHSCREEN_UPDATE_EVENT;
10927 inev.ie.timestamp = xev->time;
10928 XSETFRAME (inev.ie.frame_or_window, f);
10929
10930 for (touchpoint = device->touchpoints;
10931 touchpoint; touchpoint = touchpoint->next)
10932 {
10933 arg = Fcons (list3i (lrint (touchpoint->x),
10934 lrint (touchpoint->y),
10935 lrint (touchpoint->number)),
10936 arg);
10937 }
10938
10939 inev.ie.arg = arg;
10940 }
10941
10942 goto XI_OTHER;
10943 }
10944 case XI_TouchEnd:
10945 {
10946 struct xi_device_t *device;
10947
10948 device = xi_device_from_id (dpyinfo, xev->deviceid);
10949
10950 if (!device)
10951 goto XI_OTHER;
10952
10953 xi_unlink_touch_point (xev->detail, device);
10954
10955 f = x_any_window_to_frame (dpyinfo, xev->event);
10956
10957 if (f && device->direct_p)
10958 {
10959 inev.ie.kind = TOUCHSCREEN_END_EVENT;
10960 inev.ie.timestamp = xev->time;
10961 XSETFRAME (inev.ie.frame_or_window, f);
10962 XSETINT (inev.ie.x, lrint (xev->event_x));
10963 XSETINT (inev.ie.y, lrint (xev->event_y));
10964 XSETINT (inev.ie.arg, xev->detail);
10965 }
10966
10967 goto XI_OTHER;
10968 }
10969#endif
10768 default: 10970 default:
10769 goto XI_OTHER; 10971 goto XI_OTHER;
10770 } 10972 }
diff --git a/src/xterm.h b/src/xterm.h
index 7abe168bc6f..d9ace002d58 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -179,13 +179,24 @@ struct xi_scroll_valuator_t
179 int horizontal; 179 int horizontal;
180}; 180};
181 181
182struct xi_touch_point_t
183{
184 struct xi_touch_point_t *next;
185
186 int number;
187 double x, y;
188};
189
182struct xi_device_t 190struct xi_device_t
183{ 191{
184 int device_id; 192 int device_id;
185 int scroll_valuator_count; 193 int scroll_valuator_count;
186 int grab; 194 int grab;
195 bool master_p;
196 bool direct_p;
187 197
188 struct xi_scroll_valuator_t *valuators; 198 struct xi_scroll_valuator_t *valuators;
199 struct xi_touch_point_t *touchpoints;
189}; 200};
190#endif 201#endif
191 202