emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/pgtk 5e5cde5: Merge remote-tracking branch 'origin/master' into


From: Po Lu
Subject: feature/pgtk 5e5cde5: Merge remote-tracking branch 'origin/master' into feature/pgtk
Date: Fri, 17 Dec 2021 01:23:32 -0500 (EST)

branch: feature/pgtk
commit 5e5cde55e5be6e2d388252c3ccb0d019aee6b89e
Merge: 32b9b22 f633941
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Merge remote-tracking branch 'origin/master' into feature/pgtk
---
 doc/lispref/commands.texi  |  55 +++++
 doc/lispref/os.texi        |   7 +-
 etc/NEWS                   |  12 +
 lisp/arc-mode.el           |   8 +-
 lisp/calendar/icalendar.el |   4 +-
 lisp/epa-ks.el             |  12 +-
 lisp/gnus/gnus-search.el   |   8 +-
 lisp/gnus/nndiary.el       |   4 +-
 lisp/gnus/nnrss.el         |  16 +-
 lisp/net/soap-client.el    |   7 +-
 lisp/net/tramp-adb.el      |   4 +-
 lisp/org/ol.el             |   2 +-
 lisp/org/org-clock.el      |  12 +-
 lisp/org/org-colview.el    |   2 +-
 lisp/org/org-macro.el      |   2 +-
 lisp/org/org-macs.el       |   4 +-
 lisp/org/org-table.el      |   2 +-
 lisp/org/org.el            |   8 +-
 lisp/org/ox-icalendar.el   |   7 +-
 lisp/progmodes/project.el  |   1 +
 lisp/tar-mode.el           |   4 +-
 lisp/time.el               |   2 +-
 lisp/timezone.el           |   9 +-
 lisp/vc/vc-dispatcher.el   |  21 +-
 src/keyboard.c             |  43 ++++
 src/systime.h              |   3 +-
 src/termhooks.h            |  13 +
 src/timefns.c              |  73 ++----
 src/xfns.c                 |  21 +-
 src/xterm.c                | 604 ++++++++++++++++++++++++++++++---------------
 src/xterm.h                |  11 +
 31 files changed, 643 insertions(+), 338 deletions(-)

diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index cc1c216..136fa56 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.
 * Button-Down Events::          A button was pushed and not yet released.
 * Repeat Events::               Double and triple click (or drag, or down).
 * Motion Events::               Just moving the mouse, not pushing a button.
+* Touchscreen Events::          Tapping and moving fingers on a touchscreen.
 * Focus Events::                Moving the mouse between frames.
 * Xwidget Events::              Events generated by xwidgets.
 * Misc Events::                 Other events the system can generate.
@@ -1835,6 +1836,60 @@ small movements.  Otherwise, motion events are not 
generated as long
 as the mouse cursor remains pointing to the same glyph in the text.
 @end defvar
 
+@node Touchscreen Events
+@subsection Touchscreen Events
+@cindex touchscreen events
+@cindex support for touchscreens
+
+Some window systems provide support for input devices that react to
+the user's finger, and translate those finger movements into points at
+an on-screen position.  These input devices are known as touchscreens,
+and Emacs reports the movements they generate as @dfn{touchscreen
+events}.
+
+Most individual events generated by a touchscreen only have meaning as
+part of a larger sequence of other events: for instance, the simple
+operation of tapping the touchscreen involves the user placing and
+releasing a finger on the touchscreen, and swiping the display to
+scroll it involves placing a finger, moving it many times upwards or
+downwards, and then releasing the finger.
+
+While a simplistic model consisting of one finger is adequate for taps
+and scrolling, more complicated gestures require support for keeping
+track of multiple fingers, where the position of each finger is
+represented by a @dfn{touch point}.  For example, a ``pinch to zoom''
+gesture might consist of the user placing two fingers and moving them
+individually in opposite directions, where the distance between the
+positions of their individual points determine the amount by which to
+zoom the display, and the center of an imaginary line between those
+positions determines where to pan the display after zooming.
+
+@cindex touch point representation
+The low-level touchscreen events described below can be used to
+implement all the touch sequences described above.  In those events,
+each point is represented by a cons of an arbitrary number identifying
+the point and a mouse position list (@pxref{Click Events}) specifying
+the position of the finger when the event occurred.
+
+@table @code
+@cindex @code{touchscreen-begin} event
+@item (touchscreen-begin @var{point})
+This event is sent when @var{point} is created by the user pressing a
+finger against the touchscreen.
+
+@cindex @code{touchscreen-update} event
+@item (touchscreen-update @var{points})
+This event is sent when an point on the touchscreen has changed
+position.  @var{points} is a list of touchpoints containing the
+up-to-date positions of each touchpoint currently on the touchscreen.
+
+@cindex @code{touchscreen-end} event
+@item (touchscreen-end @var{point})
+This event is sent when @var{point} is no longer present on the
+display, because another program took the grab, or because the user
+released the finger.
+@end table
+
 @node Focus Events
 @subsection Focus Events
 @cindex focus event
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index b4efc44..de76ab4 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1352,7 +1352,7 @@ may change as higher-resolution clocks become available.
 
 @cindex time value
   Function arguments, e.g., the @var{time} argument to
-@code{current-time-string}, accept a more-general @dfn{time value}
+@code{format-time-string}, accept a more-general @dfn{time value}
 format, which can be a Lisp timestamp, @code{nil} for the current
 time, a single floating-point number for seconds, or a list
 @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
 returned.  If @var{form} is the symbol @code{integer}, this function
 returns an integer count of seconds.  If @var{form} is a positive
 integer, it specifies a clock frequency and this function returns an
-integer-pair timestamp @code{(@var{ticks}
-. @var{form})}.@footnote{Currently a positive integer @var{form}
-should be at least 65536 if the returned value is intended to be given
-to standard functions expecting Lisp timestamps.}  If @var{form} is
+integer-pair timestamp @code{(@var{ticks} . @var{form})}.  If @var{form} is
 @code{t}, this function treats it as a positive integer suitable for
 representing the timestamp; for example, it is treated as 1000000000
 if @var{time} is nil and the platform timestamp has nanosecond
diff --git a/etc/NEWS b/etc/NEWS
index 1d78f1f..61e1cd1 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1152,10 +1152,22 @@ cookies set by web pages on disk.
 This variable is bound to t during the preparation of a "*Help*" buffer.
 
 +++
+** Timestamps like (1 . 1000) now work without warnings being generated.
+For example, (time-add nil '(1 . 1000)) no longer warns that the
+(1 . 1000) acts like (1000 . 1000000).  This warning, which was a
+temporary transition aid for Emacs 27, has served its purpose.
+
++++
 ** 'date-to-time' now assumes earliest values if its argument lacks
 month, day, or time.  For example, (date-to-time "2021-12-04") now
 assumes a time of 00:00 instead of signaling an error.
 
++++
+** New events for taking advantage of touchscreen devices.
+The events 'touchscreen-down', 'touchscreen-update' and
+'touchscreen-end' have been added to take better advantage of
+touch-capable display panels.
+
 
 * Changes in Emacs 29.1 on Non-Free Operating Systems
 
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index 1fd1d66..ece30fe 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."
 
 (defun archive-unixdate (low high)
   "Stringify Unix (LOW HIGH) date."
-  (let* ((time (list high low))
-        (str (current-time-string time)))
-    (format "%s-%s-%s"
-           (substring str 8 10)
-           (substring str 4 7)
-           (format-time-string "%Y" time))))
+  (let ((system-time-locale "C"))
+    (format-time-string "%e-%b-%Y" (list high low))))
 
 (defun archive-unixtime (low high)
   "Stringify Unix (LOW HIGH) time."
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el
index 7a483d4..15778ea 100644
--- a/lisp/calendar/icalendar.el
+++ b/lisp/calendar/icalendar.el
@@ -645,10 +645,10 @@ FIXME: multiple comma-separated values should be allowed!"
           (setq second (read (substring isodatetimestring 13 15))))
        ;; FIXME: Support subseconds.
         (when (> (length isodatetimestring) 15)
-          (cl-case (aref isodatetimestring 15)
+         (pcase (aref isodatetimestring 15)
             (?Z
              (setq source-zone t))
-            ((?- ?+)
+           ((or ?- ?+)
              (setq source-zone
                    (concat "UTC" (substring isodatetimestring 15))))))
         ;; shift if necessary
diff --git a/lisp/epa-ks.el b/lisp/epa-ks.el
index 5dd6ad34..186b0ac 100644
--- a/lisp/epa-ks.el
+++ b/lisp/epa-ks.el
@@ -295,12 +295,12 @@ enough, since keyservers have strict timeout settings."
                :created
                (and  (match-string 4)
                      (not (string-empty-p (match-string 4)))
-                     (seconds-to-time
+                    (time-convert
                       (string-to-number (match-string 4))))
                :expires
                (and (match-string 5)
                     (not (string-empty-p (match-string 5)))
-                    (seconds-to-time
+                   (time-convert
                      (string-to-number (match-string 5))))
                :flags
                (mapcar (lambda (flag)
@@ -319,15 +319,11 @@ enough, since keyservers have strict timeout settings."
                :created
                (and (match-string 2)
                     (not (string-empty-p (match-string 2)))
-                    (decode-time (seconds-to-time
-                                  (string-to-number
-                                   (match-string 2)))))
+                   (decode-time (string-to-number (match-string 2))))
                :expires
                (and (match-string 3)
                     (not (string-empty-p (match-string 3)))
-                    (decode-time (seconds-to-time
-                                  (string-to-number
-                                   (match-string 3)))))
+                   (decode-time (string-to-number (match-string 3))))
                :flags
                (mapcar (lambda (flag)
                          (cdr (assq flag '((?r revoked)
diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el
index a79c106..46dc1cf 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."
        (seq-subseq
         (decode-time
          (time-subtract
-          (apply #'encode-time now)
+          (encode-time now)
           (days-to-time
            (* (string-to-number (match-string 1 value))
               (cdr (assoc (match-string 2 value)
@@ -597,7 +597,7 @@ REL-DATE, or (current-time) if REL-DATE is nil."
             ;; If DOW is given, handle that specially.
             (if (and (seq-elt d-time 6) (null (seq-elt d-time 3)))
                 (decode-time
-                 (time-subtract (apply #'encode-time now)
+                 (time-subtract (encode-time now)
                                 (days-to-time
                                  (+ (if (> (seq-elt d-time 6)
                                            (seq-elt now 6))
@@ -1257,9 +1257,7 @@ elements are present."
          (setq dmonth 1))))
     (format-time-string
      "%e-%b-%Y"
-     (apply #'encode-time
-           (append '(0 0 0)
-                   (list dday dmonth dyear))))))
+     (encode-time 0 0 0 dday dmonth dyear))))
 
 (cl-defmethod gnus-search-imap-handle-string ((engine gnus-search-imap)
                                              (str string))
diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el
index 133e030..6f8917e 100644
--- a/lisp/gnus/nndiary.el
+++ b/lisp/gnus/nndiary.el
@@ -1308,7 +1308,7 @@ all.  This may very well take some time.")
   (let ((minute (nndiary-max (nth 0 sched)))
        (hour (nndiary-max (nth 1 sched)))
        (year (nndiary-max (nth 4 sched)))
-       (time-zone (or (and (nth 6 sched) (car (nth 6 sched)))
+       (time-zone (or (car (nth 6 sched))
                       (current-time-zone))))
     (when year
       (or minute (setq minute 59))
@@ -1405,7 +1405,7 @@ all.  This may very well take some time.")
                  t))
         (dow-list (nth 5 sched))
         (year (1- this-year))
-        (time-zone (or (and (nth 6 sched) (car (nth 6 sched)))
+        (time-zone (or (car (nth 6 sched))
                        (current-time-zone))))
     ;; Special case: an asterisk in one of the days specifications means that
     ;; 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 0ac57e9..59a22f7 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"
 This function handles the ISO 8601 date format described in
 URL `https://www.w3.org/TR/NOTE-datetime', and also the RFC 822 style
 which RSS 2.0 allows."
-  (let (case-fold-search vector year month day time zone cts given)
+  (let (case-fold-search vector year month day time zone given)
     (cond ((null date))                        ; do nothing for this case
          ;; if the date is just digits (unix time stamp):
          ((string-match "^[0-9]+$" date)
@@ -481,13 +481,13 @@ which RSS 2.0 allows."
                            0
                          (decoded-time-zone decoded))))))
     (if month
-       (progn
-         (setq cts (current-time-string (encode-time 0 0 0 day month year)))
-         (format "%s, %02d %s %04d %s%s"
-                 (substring cts 0 3) day (substring cts 4 7) year time
-                 (if zone
-                     (concat " " (format-time-string "%z" nil zone))
-                   "")))
+       (concat (let ((system-time-locale "C"))
+                 (format-time-string "%a, %d %b %Y "
+                                     (encode-time 0 0 0 day month year)))
+               time
+               (if zone
+                   (format-time-string " %z" nil zone)
+                 ""))
       (message-make-date given))))
 
 ;;; data functions
diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el
index b4aed27..6f915e9 100644
--- a/lisp/net/soap-client.el
+++ b/lisp/net/soap-client.el
@@ -718,10 +718,9 @@ representing leap seconds."
                 second)
               minute hour day month year second-fraction datatype time-zone)
       (let ((time
-             (apply
-              #'encode-time (list
-                             (if new-decode-time new-decode-time-second second)
-                             minute hour day month year nil nil time-zone))))
+            (encode-time (list
+                          (if new-decode-time new-decode-time-second second)
+                          minute hour day month year nil nil time-zone))))
         (if new-decode-time
             (with-no-warnings (decode-time time nil t))
           (decode-time time))))))
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 341357d..bc94092 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -416,9 +416,9 @@ Emacs dired can't find files."
   "Sort \"ls\" output by time, descending."
   (let (time-a time-b)
     (string-match tramp-adb-ls-date-regexp a)
-    (setq time-a (apply #'encode-time (parse-time-string (match-string 0 a))))
+    (setq time-a (encode-time (parse-time-string (match-string 0 a))))
     (string-match tramp-adb-ls-date-regexp b)
-    (setq time-b (apply #'encode-time (parse-time-string (match-string 0 b))))
+    (setq time-b (encode-time (parse-time-string (match-string 0 b))))
     (time-less-p time-b time-a)))
 
 (defun tramp-adb-ls-output-name-less-p (a b)
diff --git a/lisp/org/ol.el b/lisp/org/ol.el
index aa18497..b70f199 100644
--- a/lisp/org/ol.el
+++ b/lisp/org/ol.el
@@ -1575,7 +1575,7 @@ non-nil."
          (setq link
                (format-time-string
                 (car org-time-stamp-formats)
-                (apply 'encode-time
+                (encode-time
                        (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd)
                              nil nil nil))))
          (org-link-store-props :type "calendar" :date cd)))
diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el
index 12a4c2b..2526ca7 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."
           ((match-end 2)
            ;; Two time stamps.
            (let* ((ts (float-time
-                       (apply #'encode-time
+                       (encode-time
                               (save-match-data
                                 (org-parse-time-string (match-string 2))))))
                   (te (float-time
-                       (apply #'encode-time
+                       (encode-time
                               (org-parse-time-string (match-string 3)))))
                   (dt (- (if tend (min te tend) te)
                          (if tstart (max ts tstart) ts))))
@@ -2837,7 +2837,7 @@ a number of clock tables."
           (pcase (if range (car range) (plist-get params :tstart))
             ((and (pred numberp) n)
              (pcase-let ((`(,m ,d ,y) (calendar-gregorian-from-absolute n)))
-               (apply #'encode-time (list 0 0 org-extend-today-until d m y))))
+              (encode-time 0 0 org-extend-today-until d m y)))
             (timestamp
             (seconds-to-time
              (org-matcher-time (or timestamp
@@ -2847,7 +2847,7 @@ a number of clock tables."
           (pcase (if range (nth 1 range) (plist-get params :tend))
             ((and (pred numberp) n)
              (pcase-let ((`(,m ,d ,y) (calendar-gregorian-from-absolute n)))
-               (apply #'encode-time (list 0 0 org-extend-today-until d m y))))
+              (encode-time 0 0 org-extend-today-until d m y)))
             (timestamp (seconds-to-time (org-matcher-time timestamp))))))
     (while (time-less-p start end)
       (unless (bolp) (insert "\n"))
@@ -3042,9 +3042,9 @@ Otherwise, return nil."
          (setq ts (match-string 1)
                te (match-string 3))
          (setq s (- (float-time
-                     (apply #'encode-time (org-parse-time-string te)))
+                     (encode-time (org-parse-time-string te)))
                     (float-time
-                     (apply #'encode-time (org-parse-time-string ts))))
+                     (encode-time (org-parse-time-string ts))))
                neg (< s 0)
                s (abs s)
                h (floor (/ s 3600))
diff --git a/lisp/org/org-colview.el b/lisp/org/org-colview.el
index 9794382..f93e948 100644
--- a/lisp/org/org-colview.el
+++ b/lisp/org/org-colview.el
@@ -782,7 +782,7 @@ around it."
       (setq time-after (copy-sequence time))
       (setf (nth 3 time-before) (1- (nth 3 time)))
       (setf (nth 3 time-after) (1+ (nth 3 time)))
-      (mapcar (lambda (x) (format-time-string fmt (apply #'encode-time x)))
+      (mapcar (lambda (x) (format-time-string fmt (encode-time x)))
              (list time-before time time-after)))))
 
 (defun org-columns-open-link (&optional arg)
diff --git a/lisp/org/org-macro.el b/lisp/org/org-macro.el
index c0287a2..83c35fa 100644
--- a/lisp/org/org-macro.el
+++ b/lisp/org/org-macro.el
@@ -378,7 +378,7 @@ Return value as a string."
                                  (buffer-substring
                                   (point) (line-end-position)))))
                       (when (cl-some #'identity time)
-                        (setq date (apply #'encode-time time))))))))
+                        (setq date (encode-time time))))))))
              (let ((proc (get-buffer-process buf)))
                (while (and proc (accept-process-output proc .5 nil t)))))
          (kill-buffer buf))
diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el
index 0779c3a..044056b 100644
--- a/lisp/org/org-macs.el
+++ b/lisp/org/org-macs.el
@@ -1185,7 +1185,7 @@ nil, just return 0."
    ((numberp s) s)
    ((stringp s)
     (condition-case nil
-       (float-time (apply #'encode-time (org-parse-time-string s)))
+       (float-time (encode-time (org-parse-time-string s)))
       (error 0)))
    (t 0)))
 
@@ -1252,7 +1252,7 @@ following special strings: \"<now>\", \"<today>\",
 \"<tomorrow>\", and \"<yesterday>\".
 
 Return 0. if S is not recognized as a valid value."
-  (let ((today (float-time (apply #'encode-time
+  (let ((today (float-time (encode-time
                                  (append '(0 0 0) (nthcdr 3 (decode-time)))))))
     (save-match-data
       (cond
diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el
index e34872f..a6dd8bf 100644
--- a/lisp/org/org-table.el
+++ b/lisp/org/org-table.el
@@ -2606,7 +2606,7 @@ location of point."
                     (format-time-string
                      (org-time-stamp-format
                       (string-match-p "[0-9]\\{1,2\\}:[0-9]\\{2\\}" ts))
-                     (apply #'encode-time
+                     (encode-time
                             (save-match-data (org-parse-time-string ts))))))
                 form t t))
 
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 00bbc07..253a9ef 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -13987,7 +13987,7 @@ user."
     (when (< (nth 2 org-defdecode) org-extend-today-until)
       (setf (nth 2 org-defdecode) -1)
       (setf (nth 1 org-defdecode) 59)
-      (setq org-def (apply #'encode-time org-defdecode))
+      (setq org-def (encode-time org-defdecode))
       (setq org-defdecode (decode-time org-def)))
     (let* ((timestr (format-time-string
                     (if org-with-time "%Y-%m-%d %H:%M" "%Y-%m-%d")
@@ -14471,7 +14471,7 @@ The command returns the inserted time stamp."
          time (org-fix-decoded-time t1)
          str (org-add-props
                  (format-time-string
-                  (substring tf 1 -1) (apply 'encode-time time))
+                  (substring tf 1 -1) (encode-time time))
                  nil 'mouse-face 'highlight))
     (put-text-property beg end 'display str)))
 
@@ -14726,7 +14726,7 @@ days in order to avoid rounding problems."
 
 (defun org-time-string-to-time (s)
   "Convert timestamp string S into internal time."
-  (apply #'encode-time (org-parse-time-string s)))
+  (encode-time (org-parse-time-string s)))
 
 (defun org-time-string-to-seconds (s)
   "Convert a timestamp string S into a number of seconds."
@@ -15156,7 +15156,7 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like
          (setcar time0 (or (car time0) 0))
          (setcar (nthcdr 1 time0) (or (nth 1 time0) 0))
          (setcar (nthcdr 2 time0) (or (nth 2 time0) 0))
-         (setq time (apply 'encode-time time0))))
+         (setq time (encode-time time0))))
       ;; Insert the new time-stamp, and ensure point stays in the same
       ;; category as before (i.e. not after the last position in that
       ;; category).
diff --git a/lisp/org/ox-icalendar.el b/lisp/org/ox-icalendar.el
index 16c3dc9..211d0f7 100644
--- a/lisp/org/ox-icalendar.el
+++ b/lisp/org/ox-icalendar.el
@@ -824,8 +824,7 @@ as a communication channel."
    (if (not (plist-get info :with-author)) ""
      (org-export-data (plist-get info :author) info))
    ;; Timezone.
-   (if (org-string-nw-p org-icalendar-timezone) org-icalendar-timezone
-     (cadr (current-time-zone)))
+   (or (org-string-nw-p org-icalendar-timezone) (format-time-string "%Z"))
    ;; Description.
    (org-export-data (plist-get info :title) info)
    contents))
@@ -972,7 +971,7 @@ This function assumes major mode for current buffer is
        (org-icalendar--vcalendar
        org-icalendar-combined-name
        user-full-name
-       (or (org-string-nw-p org-icalendar-timezone) (cadr (current-time-zone)))
+       (or (org-string-nw-p org-icalendar-timezone) (format-time-string "%Z"))
        org-icalendar-combined-description
        contents)))
     (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."
              user-full-name
              ;; Timezone.
              (or (org-string-nw-p org-icalendar-timezone)
-                 (cadr (current-time-zone)))
+                 (format-time-string "Z"))
              ;; Description.
              org-icalendar-combined-description
              ;; Contents.
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 8fecdbb..3b63447 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1175,6 +1175,7 @@ displayed."
     (derived-mode . dired-mode)
     (derived-mode . diff-mode)
     (derived-mode . comint-mode)
+    (derived-mode . eshell-mode)
     (derived-mode . change-log-mode))
   "List of conditions to kill buffers related to a project.
 This list is used by `project-kill-buffers'.
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
index db65561..0ca26f7 100644
--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -467,8 +467,8 @@ checksum before doing the check."
 
 (defun tar-clip-time-string (time)
   (declare (obsolete format-time-string "27.1"))
-  (let ((str (current-time-string time)))
-    (concat " " (substring str 4 16) (format-time-string " %Y" time))))
+  (let ((system-time-locale "C"))
+    (format-time-string " %b %e %H:%M %Y" time)))
 
 (defun tar-grind-file-mode (mode)
   "Construct a `rw-r--r--' string indicating MODE.
diff --git a/lisp/time.el b/lisp/time.el
index fcea064..b67315c 100644
--- a/lisp/time.el
+++ b/lisp/time.el
@@ -355,7 +355,7 @@ update which can wait for the next redisplay."
          (am-pm (if (>= hour 12) "pm" "am"))
          (minutes (substring time 14 16))
          (seconds (substring time 17 19))
-         (time-zone (car (cdr (current-time-zone now))))
+        (time-zone (format-time-string "%Z" now))
          (day (substring time 8 10))
          (year (format-time-string "%Y" now))
          (monthname (substring time 4 7))
diff --git a/lisp/timezone.el b/lisp/timezone.el
index 0fcdbdb..7a461c4 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,
 or nil if the local time zone could not be computed.
 DATE is the number of days elapsed since the (imaginary)
 Gregorian date Sunday, December 31, 1 BC."
-   (and (fboundp 'current-time-zone)
-       (let ((utc-time (timezone-time-from-absolute date seconds)))
-         (and utc-time
-              (let ((zone (current-time-zone utc-time)))
-                (and (car zone) zone))))))
+  (let ((utc-time (timezone-time-from-absolute date seconds)))
+    (and utc-time
+        (let ((zone (current-time-zone utc-time)))
+          (and (car zone) zone)))))
 
 (defun timezone-fix-time (date local timezone)
   "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 346974b..53cdb5e 100644
--- a/lisp/vc/vc-dispatcher.el
+++ b/lisp/vc/vc-dispatcher.el
@@ -127,8 +127,12 @@ preserve the setting."
   :group 'vc)
 
 (defcustom vc-command-messages nil
-  "If non-nil, display run messages from back-end commands."
-  :type 'boolean
+  "If non-nil, display and log messages about running back-end commands.
+If the value is `log', messages about running VC back-end commands are
+logged in the *Messages* buffer, but not displayed."
+  :type '(choice (const :tag "No messages" nil)
+                 (const :tag "Display and log messages" t)
+                 (const :tag "Log messages, but don't display" log))
   :group 'vc)
 
 (defcustom vc-suppress-confirm nil
@@ -311,7 +315,10 @@ case, and the process object in the asynchronous case."
                      (substring command 0 -1)
                    command)
                  " " (vc-delistify flags)
-                 " " (vc-delistify files))))
+                 " " (vc-delistify files)))
+        (vc-inhibit-message
+         (or (eq vc-command-messages 'log)
+             (eq (selected-window) (active-minibuffer-window)))))
     (save-current-buffer
       (unless (or (eq buffer t)
                  (and (stringp buffer)
@@ -335,7 +342,7 @@ case, and the process object in the asynchronous case."
                       (apply #'start-file-process command (current-buffer)
                               command squeezed))))
                (when vc-command-messages
-                 (let ((inhibit-message (eq (selected-window) 
(active-minibuffer-window))))
+                 (let ((inhibit-message vc-inhibit-message))
                    (message "Running in background: %s" full-command)))
                 ;; Get rid of the default message insertion, in case we don't
                 ;; set a sentinel explicitly.
@@ -345,11 +352,11 @@ case, and the process object in the asynchronous case."
                (when vc-command-messages
                  (vc-run-delayed
                    (let ((message-truncate-lines t)
-                         (inhibit-message (eq (selected-window) 
(active-minibuffer-window))))
+                         (inhibit-message vc-inhibit-message))
                      (message "Done in background: %s" full-command)))))
            ;; Run synchronously
            (when vc-command-messages
-             (let ((inhibit-message (eq (selected-window) 
(active-minibuffer-window))))
+             (let ((inhibit-message vc-inhibit-message))
                (message "Running in foreground: %s" full-command)))
            (let ((buffer-undo-list t))
              (setq status (apply #'process-file command nil t nil squeezed)))
@@ -364,7 +371,7 @@ case, and the process object in the asynchronous case."
                     (if (integerp status) (format "status %d" status) status)
                     full-command))
            (when vc-command-messages
-             (let ((inhibit-message (eq (selected-window) 
(active-minibuffer-window))))
+             (let ((inhibit-message vc-inhibit-message))
                (message "Done (status=%d): %s" status full-command)))))
        (vc-run-delayed
          (run-hook-with-args 'vc-post-command-functions
diff --git a/src/keyboard.c b/src/keyboard.c
index df07cf2..821a1b5 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -6013,6 +6013,46 @@ make_lispy_event (struct input_event *event)
        return list2 (Qtouch_end, position);
       }
 
+    case TOUCHSCREEN_BEGIN_EVENT:
+    case TOUCHSCREEN_END_EVENT:
+      {
+       Lisp_Object x, y, id, position;
+       struct frame *f = XFRAME (event->frame_or_window);
+
+       id = event->arg;
+       x = event->x;
+       y = event->y;
+
+       position = make_lispy_position (f, x, y, event->timestamp);
+
+       return list2 (((event->kind
+                       == TOUCHSCREEN_BEGIN_EVENT)
+                      ? Qtouchscreen_begin
+                      : Qtouchscreen_end),
+                     Fcons (id, position));
+      }
+
+    case TOUCHSCREEN_UPDATE_EVENT:
+      {
+       Lisp_Object x, y, id, position, tem, it, evt;
+       struct frame *f = XFRAME (event->frame_or_window);
+       evt = Qnil;
+
+       for (tem = event->arg; CONSP (tem); tem = XCDR (tem))
+         {
+           it = XCAR (tem);
+
+           x = XCAR (it);
+           y = XCAR (XCDR (it));
+           id = XCAR (XCDR (XCDR (it)));
+
+           position = make_lispy_position (f, x, y, event->timestamp);
+           evt = Fcons (Fcons (id, position), evt);
+         }
+
+       return list2 (Qtouchscreen_update, evt);
+      }
+
 #ifdef USE_TOOLKIT_SCROLL_BARS
 
       /* We don't have down and up events if using toolkit scroll bars,
@@ -12266,6 +12306,9 @@ See also `pre-command-hook'.  */);
               doc: /* Normal hook run when clearing the echo area.  */);
 #endif
   DEFSYM (Qecho_area_clear_hook, "echo-area-clear-hook");
+  DEFSYM (Qtouchscreen_begin, "touchscreen-begin");
+  DEFSYM (Qtouchscreen_end, "touchscreen-end");
+  DEFSYM (Qtouchscreen_update, "touchscreen-update");
   Fset (Qecho_area_clear_hook, Qnil);
 
   DEFVAR_LISP ("lucid-menu-bar-dirty-flag", Vlucid_menu_bar_dirty_flag,
diff --git a/src/systime.h b/src/systime.h
index 08ab5bd..ce9403c 100644
--- a/src/systime.h
+++ b/src/systime.h
@@ -80,8 +80,7 @@ struct lisp_time
   /* Clock count as a Lisp integer.  */
   Lisp_Object ticks;
 
-  /* Clock frequency (ticks per second) as a positive Lisp integer.
-     (TICKS . HZ) is a valid Lisp timestamp unless HZ < 65536.  */
+  /* Clock frequency (ticks per second) as a positive Lisp integer.  */
   Lisp_Object hz;
 };
 
diff --git a/src/termhooks.h b/src/termhooks.h
index b124e99..9f22187 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -280,6 +280,19 @@ enum event_kind
      In the future, this may take into account other multi-touch
      events generated from touchscreens and such.  */
   , TOUCH_END_EVENT
+
+  /* In a TOUCHSCREEN_UPDATE_EVENT, ARG is a list of elements of the
+     form (X Y ID), where X and Y are the coordinates of the
+     touchpoint relative to the top-left corner of the frame, and ID
+     is a unique number identifying the touchpoint.
+
+     In TOUCHSCREEN_BEGIN_EVENT and TOUCHSCREEN_END_EVENT, ARG is the
+     unique ID of the touchpoint, and X and Y are the frame-relative
+     positions of the touchpoint.  */
+
+  , TOUCHSCREEN_UPDATE_EVENT
+  , TOUCHSCREEN_BEGIN_EVENT
+  , TOUCHSCREEN_END_EVENT
 };
 
 /* 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 a9921cd..74b5ca8 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -69,16 +69,6 @@ enum { TM_YEAR_BASE = 1900 };
 # define FASTER_TIMEFNS 1
 #endif
 
-/* Whether to warn about Lisp timestamps (TICKS . HZ) that may be
-   instances of obsolete-format timestamps (HI . LO) where HI is
-   the high-order bits and LO the low-order 16 bits.  Currently this
-   is true, but it should change to false in a future version of
-   Emacs.  Compile with -DWARN_OBSOLETE_TIMESTAMPS=0 to see what the
-   future will be like.  */
-#ifndef WARN_OBSOLETE_TIMESTAMPS
-enum { WARN_OBSOLETE_TIMESTAMPS = true };
-#endif
-
 /* Although current-time etc. generate list-format timestamps
    (HI LO US PS), the plan is to change these functions to generate
    frequency-based timestamps (TICKS . HZ) in a future release.
@@ -817,14 +807,10 @@ decode_time_components (enum timeform form,
   return decode_ticks_hz (make_integer_mpz (), hz, result, dresult);
 }
 
-enum { DECODE_SECS_ONLY = WARN_OBSOLETE_TIMESTAMPS + 1 };
-
 /* Decode a Lisp timestamp SPECIFIED_TIME that represents a time.
 
-   FLAGS specifies conversion flags.  If FLAGS & DECODE_SECS_ONLY,
-   ignore and do not validate any sub-second components of an
-   old-format SPECIFIED_TIME.  If FLAGS & WARN_OBSOLETE_TIMESTAMPS,
-   diagnose what could be obsolete (HIGH . LOW) timestamps.
+   If DECODE_SECS_ONLY, ignore and do not validate any sub-second
+   components of an old-format SPECIFIED_TIME.
 
    If RESULT is not null, store into *RESULT the converted time;
    otherwise, store into *DRESULT the number of seconds since the
@@ -833,7 +819,7 @@ enum { DECODE_SECS_ONLY = WARN_OBSOLETE_TIMESTAMPS + 1 };
 
    Return the form of SPECIFIED-TIME.  Signal an error if unsuccessful.  */
 static enum timeform
-decode_lisp_time (Lisp_Object specified_time, int flags,
+decode_lisp_time (Lisp_Object specified_time, bool decode_secs_only,
                  struct lisp_time *result, double *dresult)
 {
   Lisp_Object high = make_fixnum (0);
@@ -854,7 +840,7 @@ decode_lisp_time (Lisp_Object specified_time, int flags,
        {
          Lisp_Object low_tail = XCDR (low);
          low = XCAR (low);
-         if (! (flags & DECODE_SECS_ONLY))
+         if (! decode_secs_only)
            {
              if (CONSP (low_tail))
                {
@@ -877,9 +863,6 @@ decode_lisp_time (Lisp_Object specified_time, int flags,
        }
       else
        {
-         if (flags & WARN_OBSOLETE_TIMESTAMPS
-             && RANGED_FIXNUMP (0, low, (1 << LO_TIME_BITS) - 1))
-           message ("obsolete timestamp with cdr %"pI"d", XFIXNUM (low));
          form = TIMEFORM_TICKS_HZ;
        }
 
@@ -1008,8 +991,7 @@ static struct lisp_time
 lisp_time_struct (Lisp_Object specified_time, enum timeform *pform)
 {
   struct lisp_time t;
-  enum timeform form
-    = decode_lisp_time (specified_time, WARN_OBSOLETE_TIMESTAMPS, &t, 0);
+  enum timeform form = decode_lisp_time (specified_time, false, &t, 0);
   if (pform)
     *pform = form;
   return t;
@@ -1034,9 +1016,8 @@ lisp_time_argument (Lisp_Object specified_time)
 static time_t
 lisp_seconds_argument (Lisp_Object specified_time)
 {
-  int flags = WARN_OBSOLETE_TIMESTAMPS | DECODE_SECS_ONLY;
   struct lisp_time lt;
-  decode_lisp_time (specified_time, flags, &lt, 0);
+  decode_lisp_time (specified_time, true, &lt, 0);
   struct timespec t = lisp_to_timespec (lt);
   if (! timespec_valid_p (t))
     time_overflow ();
@@ -1138,24 +1119,6 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
       mpz_t *ihz = &mpz[0];
       mpz_mul (*ihz, *fa, *db);
 
-      /* When warning about obsolete timestamps, if the smaller
-        denominator comes from a non-(TICKS . HZ) timestamp and could
-        generate a (TICKS . HZ) timestamp that would look obsolete,
-        arrange for the result to have a higher HZ to avoid a
-        spurious warning by a later consumer of this function's
-        returned value.  */
-      verify (1 << LO_TIME_BITS <= ULONG_MAX);
-      if (WARN_OBSOLETE_TIMESTAMPS
-         && (da_lt_db ? aform : bform) == TIMEFORM_FLOAT
-         && (da_lt_db ? bform : aform) != TIMEFORM_TICKS_HZ
-         && mpz_cmp_ui (*hzmin, 1) > 0
-         && mpz_cmp_ui (*hzmin, 1 << LO_TIME_BITS) < 0)
-       {
-         mpz_t *hzmin1 = &mpz[2 - da_lt_db];
-         mpz_set_ui (*hzmin1, 1 << LO_TIME_BITS);
-         hzmin = hzmin1;
-       }
-
       /* iticks = (fb * na) OP (fa * nb), where OP is + or -.  */
       mpz_t const *na = bignum_integer (iticks, ta.ticks);
       mpz_mul (*iticks, *fb, *na);
@@ -1177,8 +1140,7 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
             upwards by multiplying the normalized numerator and denominator
             so that the resulting denominator becomes at least hzmin.
             This rescaling avoids returning a timestamp that is less precise
-            than both a and b, or a timestamp that looks obsolete when that
-            might be a problem.  */
+            than both a and b.  */
          if (!FASTER_TIMEFNS || mpz_cmp (*ihz, *hzmin) < 0)
            {
              /* Rescale straightforwardly.  Although this might not
@@ -1303,7 +1265,7 @@ or (if you need time as a string) `format-time-string'.  
*/)
   (Lisp_Object specified_time)
 {
   double t;
-  decode_lisp_time (specified_time, 0, 0, &t);
+  decode_lisp_time (specified_time, false, 0, &t);
   return make_float (t);
 }
 
@@ -1651,12 +1613,11 @@ saving flag to be guessed.
 
 As an obsolescent calling convention, if this function is called with
 6 or more arguments, the first 6 arguments are SECOND, MINUTE, HOUR,
-DAY, MONTH, and YEAR, and specify the components of a decoded time,
-where DST assumed to be -1 and FORM is omitted.  If there are more
-than 6 arguments the *last* argument is used as ZONE and any other
-extra arguments are ignored, so that (apply #\\='encode-time
-(decode-time ...)) works.  In this obsolescent convention, DST and
-ZONE default to -1 and nil respectively.
+DAY, MONTH, and YEAR, and specify the components of a decoded time.
+If there are more than 6 arguments the *last* argument is used as ZONE
+and any other extra arguments are ignored, so that (apply
+#\\='encode-time (decode-time ...)) works.  In this obsolescent
+convention, DST and ZONE default to -1 and nil respectively.
 
 Years before 1970 are not guaranteed to work.  On some systems,
 year values as low as 1901 do work.
@@ -1703,7 +1664,7 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS)  */)
 
   /* Let SEC = floor (LT.ticks / HZ), with SUBSECTICKS the remainder.  */
   struct lisp_time lt;
-  decode_lisp_time (secarg, 0, &lt, 0);
+  decode_lisp_time (secarg, false, &lt, 0);
   Lisp_Object hz = lt.hz, sec, subsecticks;
   if (FASTER_TIMEFNS && EQ (hz, make_fixnum (1)))
     {
@@ -1756,9 +1717,7 @@ Truncate the returned value toward minus infinity.
 If FORM is nil (the default), return the same form as `current-time'.
 If FORM is a positive integer, return a pair of integers (TICKS . FORM),
 where TICKS is the number of clock ticks and FORM is the clock frequency
-in ticks per second.  (Currently the positive integer should be at least
-65536 if the returned value is expected to be given to standard functions
-expecting Lisp timestamps.)  If FORM is t, return (TICKS . PHZ), where
+in ticks per second.  If FORM is t, return (TICKS . PHZ), where
 PHZ is a suitable clock frequency in ticks per second.  If FORM is
 `integer', return an integer count of seconds.  If FORM is `list',
 return 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.  */)
      (Lisp_Object time, Lisp_Object form)
 {
   struct lisp_time t;
-  enum timeform input_form = decode_lisp_time (time, 0, &t, 0);
+  enum timeform input_form = decode_lisp_time (time, false, &t, 0);
   if (NILP (form))
     form = CURRENT_TIME_LIST ? Qlist : Qt;
   if (EQ (form, Qlist))
diff --git a/src/xfns.c b/src/xfns.c
index b569482..dc25d7b 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -2916,7 +2916,7 @@ initial_set_up_x_back_buffer (struct frame *f)
   unblock_input ();
 }
 
-#if defined HAVE_XINPUT2 && !defined USE_GTK
+#if defined HAVE_XINPUT2
 static void
 setup_xi_event_mask (struct frame *f)
 {
@@ -2927,6 +2927,9 @@ setup_xi_event_mask (struct frame *f)
   mask.mask = m = alloca (l);
   memset (m, 0, l);
   mask.mask_len = l;
+
+  block_input ();
+#ifndef USE_GTK
   mask.deviceid = XIAllMasterDevices;
 
   XISetMask (m, XI_ButtonPress);
@@ -2945,14 +2948,25 @@ setup_xi_event_mask (struct frame *f)
                  &mask, 1);
 
   memset (m, 0, l);
+#endif /* !USE_GTK */
+
   mask.deviceid = XIAllDevices;
 
   XISetMask (m, XI_PropertyEvent);
   XISetMask (m, XI_HierarchyChanged);
   XISetMask (m, XI_DeviceChanged);
+#ifdef XI_TouchBegin
+  if (FRAME_DISPLAY_INFO (f)->xi2_version >= 2)
+    {
+      XISetMask (m, XI_TouchBegin);
+      XISetMask (m, XI_TouchUpdate);
+      XISetMask (m, XI_TouchEnd);
+    }
+#endif
   XISelectEvents (FRAME_X_DISPLAY (f),
                  FRAME_X_WINDOW (f),
                  &mask, 1);
+  unblock_input ();
 }
 #endif
 
@@ -3249,6 +3263,11 @@ x_window (struct frame *f)
     unblock_input ();
   }
 #endif
+
+#ifdef HAVE_XINPUT2
+  if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+    setup_xi_event_mask (f);
+#endif
 }
 
 #else /*! USE_GTK */
diff --git a/src/xterm.c b/src/xterm.c
index 646985b..fa60a4e 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -353,6 +353,8 @@ x_extension_initialize (struct x_display_info *dpyinfo)
 static void
 x_free_xi_devices (struct x_display_info *dpyinfo)
 {
+  struct xi_touch_point_t *tem, *last;
+
   block_input ();
 
   if (dpyinfo->num_devices)
@@ -362,6 +364,14 @@ x_free_xi_devices (struct x_display_info *dpyinfo)
          XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id,
                          CurrentTime);
          xfree (dpyinfo->devices[i].valuators);
+
+         tem = dpyinfo->devices[i].touchpoints;
+         while (tem)
+           {
+             last = tem;
+             tem = tem->next;
+             xfree (last);
+           }
        }
 
       xfree (dpyinfo->devices);
@@ -407,7 +417,7 @@ x_init_master_valuators (struct x_display_info *dpyinfo)
   block_input ();
   x_free_xi_devices (dpyinfo);
   infos = XIQueryDevice (dpyinfo->display,
-                        XIAllMasterDevices,
+                        XIAllDevices,
                         &ndevices);
 
   if (!ndevices)
@@ -432,6 +442,10 @@ x_init_master_valuators (struct x_display_info *dpyinfo)
          xi_device->grab = 0;
          xi_device->valuators =
            xmalloc (sizeof *xi_device->valuators * device->num_classes);
+         xi_device->touchpoints = NULL;
+         xi_device->master_p = (device->use == XIMasterKeyboard
+                                || device->use == XIMasterPointer);
+         xi_device->direct_p = false;
 
          for (int c = 0; c < device->num_classes; ++c)
            {
@@ -442,22 +456,36 @@ x_init_master_valuators (struct x_display_info *dpyinfo)
                  {
                    XIScrollClassInfo *info =
                      (XIScrollClassInfo *) device->classes[c];
-                   struct xi_scroll_valuator_t *valuator =
-                     &xi_device->valuators[actual_valuator_count++];
-
-                   valuator->horizontal
-                     = (info->scroll_type == XIScrollTypeHorizontal);
-                   valuator->invalid_p = true;
-                   valuator->emacs_value = DBL_MIN;
-                   valuator->increment = info->increment;
-                   valuator->number = info->number;
+                   struct xi_scroll_valuator_t *valuator;
+
+                   if (xi_device->master_p)
+                     {
+                       valuator = 
&xi_device->valuators[actual_valuator_count++];
+                       valuator->horizontal
+                         = (info->scroll_type == XIScrollTypeHorizontal);
+                       valuator->invalid_p = true;
+                       valuator->emacs_value = DBL_MIN;
+                       valuator->increment = info->increment;
+                       valuator->number = info->number;
+                     }
+
                    break;
                  }
 #endif
+#ifdef XITouchClass /* XInput 2.2 */
+               case XITouchClass:
+                 {
+                   XITouchClassInfo *info;
+
+                   info = (XITouchClassInfo *) device->classes[c];
+                   xi_device->direct_p = info->mode == XIDirectTouch;
+                 }
+#endif
                default:
                  break;
                }
            }
+
          xi_device->scroll_valuator_count = actual_valuator_count;
        }
     }
@@ -484,7 +512,7 @@ x_get_scroll_valuator_delta (struct x_display_info 
*dpyinfo, int device_id,
     {
       struct xi_device_t *device = &dpyinfo->devices[i];
 
-      if (device->device_id == device_id)
+      if (device->device_id == device_id && device->master_p)
        {
          for (int j = 0; j < device->scroll_valuator_count; ++j)
            {
@@ -534,6 +562,61 @@ xi_device_from_id (struct x_display_info *dpyinfo, int 
deviceid)
   return NULL;
 }
 
+#ifdef XI_TouchBegin
+
+static void
+xi_link_touch_point (struct xi_device_t *device,
+                    int detail, double x, double y)
+{
+  struct xi_touch_point_t *touchpoint;
+
+  touchpoint = xmalloc (sizeof *touchpoint);
+  touchpoint->next = device->touchpoints;
+  touchpoint->x = x;
+  touchpoint->y = y;
+  touchpoint->number = detail;
+
+  device->touchpoints = touchpoint;
+}
+
+static void
+xi_unlink_touch_point (int detail,
+                      struct xi_device_t *device)
+{
+  struct xi_touch_point_t *last, *tem;
+
+  for (last = NULL, tem = device->touchpoints; tem;
+       last = tem, tem = tem->next)
+    {
+      if (tem->number == detail)
+       {
+         if (!last)
+           device->touchpoints = tem->next;
+         else
+           last->next = tem->next;
+
+         xfree (tem);
+         return;
+       }
+    }
+}
+
+static struct xi_touch_point_t *
+xi_find_touch_point (struct xi_device_t *device, int detail)
+{
+  struct xi_touch_point_t *point;
+
+  for (point = device->touchpoints; point; point = point->next)
+    {
+      if (point->number == detail)
+       return point;
+    }
+
+  return NULL;
+}
+
+#endif /* XI_TouchBegin */
+
 static void
 xi_grab_or_ungrab_device (struct xi_device_t *device,
                          struct x_display_info *dpyinfo,
@@ -570,7 +653,7 @@ xi_reset_scroll_valuators_for_device_id (struct 
x_display_info *dpyinfo, int id)
   struct xi_device_t *device = xi_device_from_id (dpyinfo, id);
   struct xi_scroll_valuator_t *valuator;
 
-  if (!device)
+  if (!device || !device->master_p)
     return;
 
   if (!device->scroll_valuator_count)
@@ -9981,242 +10064,250 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #endif
            goto XI_OTHER;
          case XI_Motion:
-           states = &xev->valuators;
-           values = states->values;
+           {
+             struct xi_device_t *device;
 
-           x_display_set_last_user_time (dpyinfo, xi_event->time);
+             states = &xev->valuators;
+             values = states->values;
+             device = xi_device_from_id (dpyinfo, xev->deviceid);
+
+             if (!device || !device->master_p)
+               goto XI_OTHER;
+
+             x_display_set_last_user_time (dpyinfo, xi_event->time);
 
 #ifdef HAVE_XWIDGETS
-           struct xwidget_view *xv = xwidget_view_from_window (xev->event);
-           double xv_total_x = 0.0;
-           double xv_total_y = 0.0;
+             struct xwidget_view *xv = xwidget_view_from_window (xev->event);
+             double xv_total_x = 0.0;
+             double xv_total_y = 0.0;
 #endif
 
-           for (int i = 0; i < states->mask_len * 8; i++)
-             {
-               if (XIMaskIsSet (states->mask, i))
-                 {
-                   struct xi_scroll_valuator_t *val;
-                   double delta, scroll_unit;
-                   int scroll_height;
-                   Lisp_Object window;
+             for (int i = 0; i < states->mask_len * 8; i++)
+               {
+                 if (XIMaskIsSet (states->mask, i))
+                   {
+                     struct xi_scroll_valuator_t *val;
+                     double delta, scroll_unit;
+                     int scroll_height;
+                     Lisp_Object window;
 
 
-                   /* See the comment on top of
-                      x_init_master_valuators for more details on how
-                      scroll wheel movement is reported on XInput 2.  */
-                   delta = x_get_scroll_valuator_delta (dpyinfo, xev->deviceid,
-                                                        i, *values, &val);
+                     /* See the comment on top of
+                        x_init_master_valuators for more details on how
+                        scroll wheel movement is reported on XInput 2.  */
+                     delta = x_get_scroll_valuator_delta (dpyinfo, 
xev->deviceid,
+                                                          i, *values, &val);
 
-                   if (delta != DBL_MAX)
-                     {
+                     if (delta != DBL_MAX)
+                       {
 #ifdef HAVE_XWIDGETS
-                       if (xv)
-                         {
-                           if (val->horizontal)
-                             xv_total_x += delta;
-                           else
-                             xv_total_y += delta;
+                         if (xv)
+                           {
+                             if (val->horizontal)
+                               xv_total_x += delta;
+                             else
+                               xv_total_y += delta;
 
-                           found_valuator = true;
+                             found_valuator = true;
 
-                           if (delta == 0.0)
-                             any_stop_p = true;
+                             if (delta == 0.0)
+                               any_stop_p = true;
 
-                           continue;
-                         }
+                             continue;
+                           }
 #endif
-                       if (!f)
-                         {
-                           f = x_any_window_to_frame (dpyinfo, xev->event);
+                         if (!f)
+                           {
+                             f = x_any_window_to_frame (dpyinfo, xev->event);
 
-                           if (!f)
-                             goto XI_OTHER;
-                         }
+                             if (!f)
+                               goto XI_OTHER;
+                           }
 
-                       found_valuator = true;
+                         found_valuator = true;
 
-                       if (signbit (delta) != signbit (val->emacs_value))
-                         val->emacs_value = 0;
+                         if (signbit (delta) != signbit (val->emacs_value))
+                           val->emacs_value = 0;
 
-                       val->emacs_value += delta;
+                         val->emacs_value += delta;
 
-                       if (mwheel_coalesce_scroll_events
-                           && (fabs (val->emacs_value) < 1)
-                           && (fabs (delta) > 0))
-                         continue;
+                         if (mwheel_coalesce_scroll_events
+                             && (fabs (val->emacs_value) < 1)
+                             && (fabs (delta) > 0))
+                           continue;
 
-                       bool s = signbit (val->emacs_value);
-                       inev.ie.kind = (fabs (delta) > 0
-                                       ? (val->horizontal
-                                          ? HORIZ_WHEEL_EVENT
-                                          : WHEEL_EVENT)
-                                       : TOUCH_END_EVENT);
-                       inev.ie.timestamp = xev->time;
+                         bool s = signbit (val->emacs_value);
+                         inev.ie.kind = (fabs (delta) > 0
+                                         ? (val->horizontal
+                                            ? HORIZ_WHEEL_EVENT
+                                            : WHEEL_EVENT)
+                                         : TOUCH_END_EVENT);
+                         inev.ie.timestamp = xev->time;
 
-                       XSETINT (inev.ie.x, lrint (xev->event_x));
-                       XSETINT (inev.ie.y, lrint (xev->event_y));
-                       XSETFRAME (inev.ie.frame_or_window, f);
+                         XSETINT (inev.ie.x, lrint (xev->event_x));
+                         XSETINT (inev.ie.y, lrint (xev->event_y));
+                         XSETFRAME (inev.ie.frame_or_window, f);
 
-                       if (fabs (delta) > 0)
-                         {
-                           inev.ie.modifiers = !s ? up_modifier : 
down_modifier;
-                           inev.ie.modifiers
-                             |= x_x_to_emacs_modifiers (dpyinfo,
-                                                        xev->mods.effective);
-                         }
+                         if (fabs (delta) > 0)
+                           {
+                             inev.ie.modifiers = !s ? up_modifier : 
down_modifier;
+                             inev.ie.modifiers
+                               |= x_x_to_emacs_modifiers (dpyinfo,
+                                                          xev->mods.effective);
+                           }
 
-                       window = window_from_coordinates (f, xev->event_x,
-                                                         xev->event_y, NULL,
-                                                         false, false);
+                         window = window_from_coordinates (f, xev->event_x,
+                                                           xev->event_y, NULL,
+                                                           false, false);
 
-                       if (WINDOWP (window))
-                         scroll_height = XWINDOW (window)->pixel_height;
-                       else
-                         /* EVENT_X and EVENT_Y can be outside the
-                            frame if F holds the input grab, so fall
-                            back to the height of the frame instead.  */
-                         scroll_height = FRAME_PIXEL_HEIGHT (f);
+                         if (WINDOWP (window))
+                           scroll_height = XWINDOW (window)->pixel_height;
+                         else
+                           /* EVENT_X and EVENT_Y can be outside the
+                              frame if F holds the input grab, so fall
+                              back to the height of the frame instead.  */
+                           scroll_height = FRAME_PIXEL_HEIGHT (f);
 
-                       scroll_unit = pow (scroll_height, 2.0 / 3.0);
+                         scroll_unit = pow (scroll_height, 2.0 / 3.0);
 
-                       if (NUMBERP (Vx_scroll_event_delta_factor))
-                         scroll_unit *= XFLOATINT 
(Vx_scroll_event_delta_factor);
+                         if (NUMBERP (Vx_scroll_event_delta_factor))
+                           scroll_unit *= XFLOATINT 
(Vx_scroll_event_delta_factor);
 
-                       if (fabs (delta) > 0)
-                         {
-                           if (val->horizontal)
-                             {
-                               inev.ie.arg
-                                 = list3 (Qnil,
-                                          make_float (val->emacs_value
-                                                      * scroll_unit),
-                                          make_float (0));
-                             }
-                           else
-                             {
-                               inev.ie.arg = list3 (Qnil, make_float (0),
-                                                    make_float 
(val->emacs_value
-                                                                * 
scroll_unit));
-                             }
-                         }
-                       else
-                         {
-                           inev.ie.arg = Qnil;
-                         }
+                         if (fabs (delta) > 0)
+                           {
+                             if (val->horizontal)
+                               {
+                                 inev.ie.arg
+                                   = list3 (Qnil,
+                                            make_float (val->emacs_value
+                                                        * scroll_unit),
+                                            make_float (0));
+                               }
+                             else
+                               {
+                                 inev.ie.arg = list3 (Qnil, make_float (0),
+                                                      make_float 
(val->emacs_value
+                                                                  * 
scroll_unit));
+                               }
+                           }
+                         else
+                           {
+                             inev.ie.arg = Qnil;
+                           }
 
-                       kbd_buffer_store_event_hold (&inev.ie, hold_quit);
+                         kbd_buffer_store_event_hold (&inev.ie, hold_quit);
 
-                       val->emacs_value = 0;
-                     }
-                   values++;
-                 }
+                         val->emacs_value = 0;
+                       }
+                     values++;
+                   }
 
-               inev.ie.kind = NO_EVENT;
-             }
+                 inev.ie.kind = NO_EVENT;
+               }
 
 #ifdef HAVE_XWIDGETS
-           if (xv)
-             {
-               if (found_valuator)
-                 xwidget_scroll (xv, xev->event_x, xev->event_y,
-                                 xv_total_x, xv_total_y, xev->mods.effective,
-                                 xev->time, any_stop_p);
-               else
-                 xwidget_motion_notify (xv, xev->event_x, xev->event_y,
-                                        xev->mods.effective, xev->time);
+             if (xv)
+               {
+                 if (found_valuator)
+                   xwidget_scroll (xv, xev->event_x, xev->event_y,
+                                   xv_total_x, xv_total_y, xev->mods.effective,
+                                   xev->time, any_stop_p);
+                 else
+                   xwidget_motion_notify (xv, xev->event_x, xev->event_y,
+                                          xev->mods.effective, xev->time);
 
-               goto XI_OTHER;
-             }
+                 goto XI_OTHER;
+               }
 #endif
-           if (found_valuator)
-             goto XI_OTHER;
+             if (found_valuator)
+               goto XI_OTHER;
 
-           ev.x = lrint (xev->event_x);
-           ev.y = lrint (xev->event_y);
-           ev.window = xev->event;
-           ev.time = xev->time;
+             ev.x = lrint (xev->event_x);
+             ev.y = lrint (xev->event_y);
+             ev.window = xev->event;
+             ev.time = xev->time;
 
-           previous_help_echo_string = help_echo_string;
-           help_echo_string = Qnil;
+             previous_help_echo_string = help_echo_string;
+             help_echo_string = Qnil;
 
-           if (hlinfo->mouse_face_hidden)
-             {
-               hlinfo->mouse_face_hidden = false;
-               clear_mouse_face (hlinfo);
-             }
+             if (hlinfo->mouse_face_hidden)
+               {
+                 hlinfo->mouse_face_hidden = false;
+                 clear_mouse_face (hlinfo);
+               }
 
-           f = mouse_or_wdesc_frame (dpyinfo, xev->event);
+             f = mouse_or_wdesc_frame (dpyinfo, xev->event);
 
 #ifdef USE_GTK
-           if (f && xg_event_is_for_scrollbar (f, event))
-             f = 0;
+             if (f && xg_event_is_for_scrollbar (f, event))
+               f = 0;
 #endif
-           if (f)
-             {
-               /* Maybe generate a SELECT_WINDOW_EVENT for
-                  `mouse-autoselect-window' but don't let popup menus
-                  interfere with this (Bug#1261).  */
-               if (!NILP (Vmouse_autoselect_window)
-                   && !popup_activated ()
-                   /* Don't switch if we're currently in the minibuffer.
-                      This tries to work around problems where the
-                      minibuffer gets unselected unexpectedly, and where
-                      you then have to move your mouse all the way down to
-                      the minibuffer to select it.  */
-                   && !MINI_WINDOW_P (XWINDOW (selected_window))
-                   /* With `focus-follows-mouse' non-nil create an event
-                      also when the target window is on another frame.  */
-                   && (f == XFRAME (selected_frame)
-                       || !NILP (focus_follows_mouse)))
-                 {
-                   static Lisp_Object last_mouse_window;
-                   Lisp_Object window = window_from_coordinates (f, ev.x, 
ev.y, 0, false, false);
-
-                   /* A window will be autoselected only when it is not
-                      selected now and the last mouse movement event was
-                      not in it.  The remainder of the code is a bit vague
-                      wrt what a "window" is.  For immediate autoselection,
-                      the window is usually the entire window but for GTK
-                      where the scroll bars don't count.  For delayed
-                      autoselection the window is usually the window's text
-                      area including the margins.  */
-                   if (WINDOWP (window)
-                       && !EQ (window, last_mouse_window)
-                       && !EQ (window, selected_window))
-                     {
-                       inev.ie.kind = SELECT_WINDOW_EVENT;
-                       inev.ie.frame_or_window = window;
-                     }
+             if (f)
+               {
+                 /* Maybe generate a SELECT_WINDOW_EVENT for
+                    `mouse-autoselect-window' but don't let popup menus
+                    interfere with this (Bug#1261).  */
+                 if (!NILP (Vmouse_autoselect_window)
+                     && !popup_activated ()
+                     /* Don't switch if we're currently in the minibuffer.
+                        This tries to work around problems where the
+                        minibuffer gets unselected unexpectedly, and where
+                        you then have to move your mouse all the way down to
+                        the minibuffer to select it.  */
+                     && !MINI_WINDOW_P (XWINDOW (selected_window))
+                     /* With `focus-follows-mouse' non-nil create an event
+                        also when the target window is on another frame.  */
+                     && (f == XFRAME (selected_frame)
+                         || !NILP (focus_follows_mouse)))
+                   {
+                     static Lisp_Object last_mouse_window;
+                     Lisp_Object window = window_from_coordinates (f, ev.x, 
ev.y, 0, false, false);
+
+                     /* A window will be autoselected only when it is not
+                        selected now and the last mouse movement event was
+                        not in it.  The remainder of the code is a bit vague
+                        wrt what a "window" is.  For immediate autoselection,
+                        the window is usually the entire window but for GTK
+                        where the scroll bars don't count.  For delayed
+                        autoselection the window is usually the window's text
+                        area including the margins.  */
+                     if (WINDOWP (window)
+                         && !EQ (window, last_mouse_window)
+                         && !EQ (window, selected_window))
+                       {
+                         inev.ie.kind = SELECT_WINDOW_EVENT;
+                         inev.ie.frame_or_window = window;
+                       }
 
-                   /* Remember the last window where we saw the mouse.  */
-                   last_mouse_window = window;
-                 }
+                     /* Remember the last window where we saw the mouse.  */
+                     last_mouse_window = window;
+                   }
 
-               if (!x_note_mouse_movement (f, &ev))
-                 help_echo_string = previous_help_echo_string;
-             }
-           else
-             {
+                 if (!x_note_mouse_movement (f, &ev))
+                   help_echo_string = previous_help_echo_string;
+               }
+             else
+               {
 #ifndef USE_TOOLKIT_SCROLL_BARS
-               struct scroll_bar *bar
-                 = x_window_to_scroll_bar (xi_event->display, xev->event, 2);
+                 struct scroll_bar *bar
+                   = x_window_to_scroll_bar (xi_event->display, xev->event, 2);
 
-               if (bar)
-                 x_scroll_bar_note_movement (bar, &ev);
+                 if (bar)
+                   x_scroll_bar_note_movement (bar, &ev);
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
-               /* If we move outside the frame, then we're
-                  certainly no longer on any text in the frame.  */
-               clear_mouse_face (hlinfo);
-             }
+                 /* If we move outside the frame, then we're
+                    certainly no longer on any text in the frame.  */
+                 clear_mouse_face (hlinfo);
+               }
 
-           /* If the contents of the global variable help_echo_string
-              has changed, generate a HELP_EVENT.  */
-           if (!NILP (help_echo_string)
-               || !NILP (previous_help_echo_string))
-             do_help = 1;
-           goto XI_OTHER;
+             /* If the contents of the global variable help_echo_string
+                has changed, generate a HELP_EVENT.  */
+             if (!NILP (help_echo_string)
+                 || !NILP (previous_help_echo_string))
+               do_help = 1;
+             goto XI_OTHER;
+           }
          case XI_ButtonRelease:
          case XI_ButtonPress:
            {
@@ -10242,6 +10333,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
              device = xi_device_from_id (dpyinfo, xev->deviceid);
 
+             if (!device || !device->master_p)
+               goto XI_OTHER;
+
              bv.button = xev->detail;
              bv.type = xev->evtype == XI_ButtonPress ? ButtonPress : 
ButtonRelease;
              bv.x = lrint (xev->event_x);
@@ -10408,6 +10502,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              int copy_bufsiz = sizeof (copy_buffer);
              ptrdiff_t i;
              int nchars, len;
+             struct xi_device_t *device;
+
+             device = xi_device_from_id (dpyinfo, xev->deviceid);
+
+             if (!device || !device->master_p)
+               goto XI_OTHER;
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
              /* Dispatch XI_KeyPress events when in menu.  */
@@ -10765,6 +10865,108 @@ handle_one_xevent (struct x_display_info *dpyinfo,
          case XI_DeviceChanged:
            x_init_master_valuators (dpyinfo);
            goto XI_OTHER;
+#ifdef XI_TouchBegin
+         case XI_TouchBegin:
+           {
+             struct xi_device_t *device;
+             device = xi_device_from_id (dpyinfo, xev->deviceid);
+
+             if (!device)
+               goto XI_OTHER;
+
+             if (xi_find_touch_point (device, xev->detail))
+               emacs_abort ();
+
+             f = x_any_window_to_frame (dpyinfo, xev->event);
+
+             if (f && device->direct_p)
+               {
+                 xi_link_touch_point (device, xev->detail, xev->event_x,
+                                      xev->event_y);
+
+                 inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
+                 inev.ie.timestamp = xev->time;
+                 XSETFRAME (inev.ie.frame_or_window, f);
+                 XSETINT (inev.ie.x, lrint (xev->event_x));
+                 XSETINT (inev.ie.y, lrint (xev->event_y));
+                 XSETINT (inev.ie.arg, xev->detail);
+
+                 XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
+                                     xev->detail, xev->event, XIAcceptTouch);
+               }
+             else
+               XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
+                                   xev->detail, xev->event, XIRejectTouch);
+
+             goto XI_OTHER;
+           }
+         case XI_TouchUpdate:
+           {
+             struct xi_device_t *device;
+             struct xi_touch_point_t *touchpoint;
+             Lisp_Object arg = Qnil;
+
+             device = xi_device_from_id (dpyinfo, xev->deviceid);
+
+             if (!device)
+               goto XI_OTHER;
+
+             touchpoint = xi_find_touch_point (device, xev->detail);
+
+             if (!touchpoint)
+               emacs_abort ();
+
+             touchpoint->x = xev->event_x;
+             touchpoint->y = xev->event_y;
+
+             f = x_any_window_to_frame (dpyinfo, xev->event);
+
+             if (f && device->direct_p)
+               {
+                 inev.ie.kind = TOUCHSCREEN_UPDATE_EVENT;
+                 inev.ie.timestamp = xev->time;
+                 XSETFRAME (inev.ie.frame_or_window, f);
+
+                 for (touchpoint = device->touchpoints;
+                      touchpoint; touchpoint = touchpoint->next)
+                   {
+                     arg = Fcons (list3i (lrint (touchpoint->x),
+                                          lrint (touchpoint->y),
+                                          lrint (touchpoint->number)),
+                                  arg);
+                   }
+
+                 inev.ie.arg = arg;
+               }
+
+             goto XI_OTHER;
+           }
+         case XI_TouchEnd:
+           {
+             struct xi_device_t *device;
+
+             device = xi_device_from_id (dpyinfo, xev->deviceid);
+
+             if (!device)
+               goto XI_OTHER;
+
+             xi_unlink_touch_point (xev->detail, device);
+
+             f = x_any_window_to_frame (dpyinfo, xev->event);
+
+             if (f && device->direct_p)
+               {
+                 inev.ie.kind = TOUCHSCREEN_END_EVENT;
+                 inev.ie.timestamp = xev->time;
+                 XSETFRAME (inev.ie.frame_or_window, f);
+                 XSETINT (inev.ie.x, lrint (xev->event_x));
+                 XSETINT (inev.ie.y, lrint (xev->event_y));
+                 XSETINT (inev.ie.arg, xev->detail);
+               }
+
+             goto XI_OTHER;
+           }
+#endif
          default:
            goto XI_OTHER;
          }
diff --git a/src/xterm.h b/src/xterm.h
index 7abe168..d9ace00 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -179,13 +179,24 @@ struct xi_scroll_valuator_t
   int horizontal;
 };
 
+struct xi_touch_point_t
+{
+  struct xi_touch_point_t *next;
+
+  int number;
+  double x, y;
+};
+
 struct xi_device_t
 {
   int device_id;
   int scroll_valuator_count;
   int grab;
+  bool master_p;
+  bool direct_p;
 
   struct xi_scroll_valuator_t *valuators;
+  struct xi_touch_point_t *touchpoints;
 };
 #endif
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]