diff options
author | Po Lu <luangruo@yahoo.com> | 2021-12-17 14:23:07 +0800 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2021-12-17 14:23:07 +0800 |
commit | 5e5cde55e5be6e2d388252c3ccb0d019aee6b89e (patch) | |
tree | 339463076073de968bfe854c4813f0d47b6e34d5 | |
parent | 32b9b22f66b1afcc614d5f76860d56d5630c5bc4 (diff) | |
parent | f6339412eebdc027b00263ae2b5c38a029e2f7b4 (diff) | |
download | emacs-5e5cde55e5be6e2d388252c3ccb0d019aee6b89e.tar.gz |
Merge remote-tracking branch 'origin/master' into feature/pgtk
-rw-r--r-- | doc/lispref/commands.texi | 55 | ||||
-rw-r--r-- | doc/lispref/os.texi | 7 | ||||
-rw-r--r-- | etc/NEWS | 12 | ||||
-rw-r--r-- | lisp/arc-mode.el | 8 | ||||
-rw-r--r-- | lisp/calendar/icalendar.el | 4 | ||||
-rw-r--r-- | lisp/epa-ks.el | 12 | ||||
-rw-r--r-- | lisp/gnus/gnus-search.el | 8 | ||||
-rw-r--r-- | lisp/gnus/nndiary.el | 4 | ||||
-rw-r--r-- | lisp/gnus/nnrss.el | 16 | ||||
-rw-r--r-- | lisp/net/soap-client.el | 7 | ||||
-rw-r--r-- | lisp/net/tramp-adb.el | 4 | ||||
-rw-r--r-- | lisp/org/ol.el | 2 | ||||
-rw-r--r-- | lisp/org/org-clock.el | 12 | ||||
-rw-r--r-- | lisp/org/org-colview.el | 2 | ||||
-rw-r--r-- | lisp/org/org-macro.el | 2 | ||||
-rw-r--r-- | lisp/org/org-macs.el | 4 | ||||
-rw-r--r-- | lisp/org/org-table.el | 2 | ||||
-rw-r--r-- | lisp/org/org.el | 8 | ||||
-rw-r--r-- | lisp/org/ox-icalendar.el | 7 | ||||
-rw-r--r-- | lisp/progmodes/project.el | 1 | ||||
-rw-r--r-- | lisp/tar-mode.el | 4 | ||||
-rw-r--r-- | lisp/time.el | 2 | ||||
-rw-r--r-- | lisp/timezone.el | 9 | ||||
-rw-r--r-- | lisp/vc/vc-dispatcher.el | 21 | ||||
-rw-r--r-- | src/keyboard.c | 43 | ||||
-rw-r--r-- | src/systime.h | 3 | ||||
-rw-r--r-- | src/termhooks.h | 13 | ||||
-rw-r--r-- | src/timefns.c | 73 | ||||
-rw-r--r-- | src/xfns.c | 21 | ||||
-rw-r--r-- | src/xterm.c | 604 | ||||
-rw-r--r-- | src/xterm.h | 11 |
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. * 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 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. @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 @@ -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 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." (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 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!" (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 5dd6ad34d74..186b0ac9d1c 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 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." (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 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.") (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 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" 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 b4aed279819..6f915e97452 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 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." "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 aa1849715c3..b70f1996d54 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 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." ((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 9794382d8a4..f93e948bdcd 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 c0287a25a55..83c35faea41 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 0779c3a82c8..044056b7a04 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 e34872fb491..a6dd8bff20f 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 00bbc076881..253a9efa27c 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 16c3dc9a029..211d0f716b8 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 8fecdbb61cf..3b634471ace 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 db655619bed..0ca26f770c4 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 fcea064b4cf..b67315cf630 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 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, 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 346974bdba8..53cdb5eba84 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 df07cf290b8..821a1b576be 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 08ab5bdde33..ce9403c931d 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 b124e995292..9f22187b841 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 a9921cdc108..74b5ca8d515 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, <, 0); + decode_lisp_time (specified_time, true, <, 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, <, 0); + decode_lisp_time (secarg, false, <, 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 b5694829aef..dc25d7bfca2 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 646985bdc20..fa60a4e8745 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 7abe168bc6f..d9ace002d58 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 |