commit 281f48f19ecad706a639d57cb937afb0b97eded7 (HEAD, refs/remotes/origin/master) Author: Jim Porter Date: Tue Jan 17 16:59:13 2023 -0800 ; Fix Eshell prompt tests when the current user is root * test/lisp/eshell/em-prompt-tests.el (em-prompt-test/field-properties) (em-prompt-test/field-properties/no-highlight): Handle the case when the current user is root. diff --git a/test/lisp/eshell/em-prompt-tests.el b/test/lisp/eshell/em-prompt-tests.el index 91464a98c26..db45e2ae3a7 100644 --- a/test/lisp/eshell/em-prompt-tests.el +++ b/test/lisp/eshell/em-prompt-tests.el @@ -44,7 +44,8 @@ em-prompt-test/field-properties (should (equal-including-properties last-prompt (propertize - (format "%s $ " (directory-file-name default-directory)) + (format "%s %s " (directory-file-name default-directory) + (if (= (file-user-uid) 0) "#" "$")) 'read-only t 'field 'prompt 'font-lock-face 'eshell-prompt @@ -68,7 +69,8 @@ em-prompt-test/field-properties/no-highlight (should (equal-including-properties last-prompt (propertize - (format "%s $ " (directory-file-name default-directory)) + (format "%s %s " (directory-file-name default-directory) + (if (= (file-user-uid) 0) "#" "$")) 'field 'prompt 'front-sticky '(field) 'rear-nonsticky '(field)))) commit 7ff5c0d7045dd105c604c3f09130693db1200ff9 Author: Paul Eggert Date: Tue Jan 17 15:38:38 2023 -0800 Port xattr handling to Fedora 9 Problem reported by Po Lu (Bug#60843). * m4/xattr.m4: Sync from Gnulib. diff --git a/m4/xattr.m4 b/m4/xattr.m4 index 6141515652a..0e179cc0d1d 100644 --- a/m4/xattr.m4 +++ b/m4/xattr.m4 @@ -1,5 +1,5 @@ # xattr.m4 - check for Extended Attributes (Linux) -# serial 5 +# serial 6 # Copyright (C) 2003-2023 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation @@ -17,23 +17,33 @@ AC_DEFUN AC_SUBST([LIB_XATTR]) if test "$use_xattr" = yes; then - AC_CHECK_HEADERS([attr/error_context.h attr/libattr.h]) - use_xattr=no - if test "$ac_cv_header_attr_libattr_h" = yes \ - && test "$ac_cv_header_attr_error_context_h" = yes; then - xattr_saved_LIBS=$LIBS - AC_SEARCH_LIBS([attr_copy_file], [attr], - [test "$ac_cv_search_attr_copy_file" = "none required" || - LIB_XATTR="$ac_cv_search_attr_copy_file"]) - AC_CHECK_FUNCS([attr_copy_file]) - LIBS=$xattr_saved_LIBS - if test "$ac_cv_func_attr_copy_file" = yes; then - use_xattr=yes - fi - fi - if test $use_xattr = no; then + AC_CACHE_CHECK([for xattr library with ATTR_ACTION_PERMISSIONS], + [gl_cv_xattr_lib], + [gl_cv_xattr_lib=no + AC_LANG_CONFTEST( + [AC_LANG_PROGRAM( + [[#include + #include + static int + is_attr_permissions (const char *name, struct error_context *ctx) + { + return attr_copy_action (name, ctx) == ATTR_ACTION_PERMISSIONS; + } + ]], + [[return attr_copy_fd ("/", 0, "/", 0, is_attr_permissions, 0); + ]])]) + AC_LINK_IFELSE([], + [gl_cv_xattr_lib='none required'], + [xattr_saved_LIBS=$LIBS + LIBS="-lattr $LIBS" + AC_LINK_IFELSE([], [gl_cv_xattr_lib=-lattr]) + LIBS=$xattr_saved_LIBS])]) + if test "$gl_cv_xattr_lib" = no; then AC_MSG_WARN([libattr development library was not found or not usable.]) AC_MSG_WARN([AC_PACKAGE_NAME will be built without xattr support.]) + use_xattr=no + elif test "$gl_cv_xattr_lib" != 'none required'; then + LIB_XATTR=$gl_cv_xattr_lib fi fi if test "$use_xattr" = yes; then commit b9ae9d3ff8e5b837d425153822be24c51d3fac84 Author: Eli Zaretskii Date: Tue Jan 17 19:45:12 2023 +0200 ; * src/xterm.c (handle_one_xevent): Fix GTK build. (Bug#60883) diff --git a/src/xterm.c b/src/xterm.c index 1373045393a..1325d923be9 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -24483,6 +24483,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, } } +#ifndef HAVE_EXT_TOOL_BAR /* Now see if the touchpoint was previously on the tool bar. If it was, release the tool bar. */ @@ -24507,6 +24508,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, /* Now clear the tool bar device. */ FRAME_OUTPUT_DATA (f)->tool_bar_touch_device = 0; } +#endif goto XI_OTHER; } commit 013ab7e2a83afa7fb577c356ae686439a2906f34 Author: Michael Albinus Date: Tue Jan 17 16:00:08 2023 +0100 Complete implementation of `file-user-id' * lisp/net/ange-ftp.el (ange-ftp-file-user-uid): New defun. Mark it as file name handler for `file-user-uid'. * lisp/net/tramp-archive.el (tramp-archive-handle-file-user-uid): Move up. Protect `file-user-id' call for older Emacs versions. * lisp/net/tramp-crypt.el (tramp-crypt-file-name-handler-alist): Remove 'file-user-uid'. * test/lisp/net/tramp-archive-tests.el (tramp-archive-test44-file-user-uid): New test. (tramp-archive-test48-auto-load) (tramp-archive-test48-delay-load): Rename. * test/lisp/net/tramp-tests.el (tramp-test44-file-user-uid): New test. (tramp--test-asynchronous-requests-timeout): Adapt docstring. (tramp-test45-asynchronous-requests) (tramp-test46-dired-compress-file) (tramp-test46-dired-compress-dir, tramp-test47-read-password) (tramp-test48-auto-load, tramp-test48-delay-load) (tramp-test48-recursive-load, tramp-test48-remote-load-path) (tramp-test49-unload): Rename. diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el index a14122f815a..e21367135d3 100644 --- a/lisp/net/ange-ftp.el +++ b/lisp/net/ange-ftp.el @@ -4379,6 +4379,10 @@ ange-ftp-find-backup-file-name ;; or return nil meaning don't make a backup. (if ange-ftp-make-backup-files (ange-ftp-real-find-backup-file-name fn))) + +(defun ange-ftp-file-user-uid () + ;; Return "don't know" value. + -1) ;;; Define the handler for special file names ;;; that causes ange-ftp to be invoked. @@ -4519,6 +4523,9 @@ ange-ftp-hook-function (put 'file-notify-add-watch 'ange-ftp 'ignore) (put 'file-notify-rm-watch 'ange-ftp 'ignore) (put 'file-notify-valid-p 'ange-ftp 'ignore) + +;; Return the "don't know' value for remote user uid. +(put 'file-user-uid 'ange-ftp 'ange-ftp-file-user-uid) ;;; Define ways of getting at unmodified Emacs primitives, ;;; turning off our handler. diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el index b9cf85bd843..7c1f578d085 100644 --- a/lisp/net/tramp-archive.el +++ b/lisp/net/tramp-archive.el @@ -670,6 +670,13 @@ tramp-archive-handle-file-truename (setq local (expand-file-name local (file-name-directory localname)))) (concat (file-truename archive) local)))) +(defun tramp-archive-handle-file-user-uid () + "Like `user-uid' for file archives." + (with-parsed-tramp-archive-file-name default-directory nil + (let ((default-directory (file-name-directory archive))) + ;; `file-user-uid' exists since Emacs 30.1. + (tramp-compat-funcall 'file-user-uid)))) + (defun tramp-archive-handle-insert-directory (filename switches &optional wildcard full-directory-p) "Like `insert-directory' for file archives." @@ -702,12 +709,6 @@ tramp-archive-handle-temporary-file-directory (let ((default-directory (file-name-directory archive))) (temporary-file-directory)))) -(defun tramp-archive-handle-file-user-uid () - "Like `user-uid' for file archives." - (with-parsed-tramp-archive-file-name default-directory nil - (let ((default-directory (file-name-directory archive))) - (file-user-uid)))) - (defun tramp-archive-handle-not-implemented (operation &rest args) "Generic handler for operations not implemented for file archives." (let ((v (ignore-errors diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el index b9d0d96eccc..afd3166d161 100644 --- a/lisp/net/tramp-crypt.el +++ b/lisp/net/tramp-crypt.el @@ -204,7 +204,7 @@ tramp-crypt-file-name-handler-alist (file-symlink-p . tramp-handle-file-symlink-p) (file-system-info . tramp-crypt-handle-file-system-info) ;; `file-truename' performed by default handler. - (file-user-uid . tramp-handle-file-user-uid) + ;; `file-user-uid' performed by default-handler. (file-writable-p . tramp-crypt-handle-file-writable-p) (find-backup-file-name . tramp-handle-find-backup-file-name) ;; `get-file-buffer' performed by default handler. diff --git a/test/lisp/net/tramp-archive-tests.el b/test/lisp/net/tramp-archive-tests.el index 59b7ed9cf7c..8fe1dbd8d0b 100644 --- a/test/lisp/net/tramp-archive-tests.el +++ b/test/lisp/net/tramp-archive-tests.el @@ -878,7 +878,18 @@ tramp-archive-test43-file-system-info (zerop (nth 1 fsi)) (zerop (nth 2 fsi)))))) -(ert-deftest tramp-archive-test47-auto-load () +;; `file-user-uid' was introduced in Emacs 30.1. +(ert-deftest tramp-archive-test44-file-user-uid () + "Check that `file-user-uid' returns proper values." + (skip-unless tramp-archive-enabled) + (skip-unless (fboundp 'file-user-uid)) + + (let ((default-directory tramp-archive-test-archive)) + ;; `file-user-uid' exists since Emacs 30.1. We don't want to see + ;; compiler warnings for older Emacsen. + (should (integerp (with-no-warnings (file-user-uid)))))) + +(ert-deftest tramp-archive-test48-auto-load () "Check that `tramp-archive' autoloads properly." :tags '(:expensive-test) (skip-unless tramp-archive-enabled) @@ -923,7 +934,7 @@ tramp-archive-test47-auto-load (format "(setq tramp-archive-enabled %s)" enabled)) (shell-quote-argument (format code file))))))))))) -(ert-deftest tramp-archive-test47-delay-load () +(ert-deftest tramp-archive-test48-delay-load () "Check that `tramp-archive' is loaded lazily, only when needed." :tags '(:expensive-test) (skip-unless tramp-archive-enabled) diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 168933b6b46..0932a53f4b1 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -33,7 +33,7 @@ ;; remote host, set this environment variable to "/dev/null" or ;; whatever is appropriate on your system. -;; For slow remote connections, `tramp-test44-asynchronous-requests' +;; For slow remote connections, `tramp-test45-asynchronous-requests' ;; might be too heavy. Setting $REMOTE_PARALLEL_PROCESSES to a proper ;; value less than 10 could help. @@ -6297,7 +6297,7 @@ tramp-test39-make-lock-file-name (skip-unless (and (fboundp 'file-locked-p) (fboundp 'make-lock-file-name))) ;; `lock-file', `unlock-file', `file-locked-p' and - ;; `make-lock-file-name' exists since Emacs 28.1. We don't want to + ;; `make-lock-file-name' exist since Emacs 28.1. We don't want to ;; see compiler warnings for older Emacsen. (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil))) (let ((tmp-name1 (tramp--test-make-temp-name nil quoted)) @@ -7076,11 +7076,40 @@ tramp-test43-file-system-info (dotimes (i (length fsi)) (should (natnump (or (nth i fsi) 0)))))) -;; `tramp-test44-asynchronous-requests' could be blocked. So we set a +;; `file-user-uid' was introduced in Emacs 30.1. +(ert-deftest tramp-test44-file-user-uid () + "Check that `file-user-uid' and `tramp-get-remote-*' return proper values." + (skip-unless (tramp--test-enabled)) + + (let ((default-directory ert-remote-temporary-file-directory)) + ;; `file-user-uid' exists since Emacs 30.1. We don't want to see + ;; compiler warnings for older Emacsen. + (when (fboundp 'file-user-uid) + (should (integerp (with-no-warnings (file-user-uid))))) + + (with-parsed-tramp-file-name default-directory nil + (should (or (integerp (tramp-get-remote-uid v 'integer)) + (null (tramp-get-remote-uid v 'integer)))) + (should (or (stringp (tramp-get-remote-uid v 'string)) + (null (tramp-get-remote-uid v 'string)))) + + (should (or (integerp (tramp-get-remote-gid v 'integer)) + (null (tramp-get-remote-gid v 'integer)))) + (should (or (stringp (tramp-get-remote-gid v 'string)) + (null (tramp-get-remote-gid v 'string)))) + + (when-let ((groups (tramp-get-remote-groups v 'integer))) + (should (consp groups)) + (dolist (group groups) (should (integerp group)))) + (when-let ((groups (tramp-get-remote-groups v 'string))) + (should (consp groups)) + (dolist (group groups) (should (stringp group))))))) + +;; `tramp-test45-asynchronous-requests' could be blocked. So we set a ;; timeout of 300 seconds, and we send a SIGUSR1 signal after 300 ;; seconds. Similar check is performed in the timer function. (defconst tramp--test-asynchronous-requests-timeout 300 - "Timeout for `tramp-test44-asynchronous-requests'.") + "Timeout for `tramp-test45-asynchronous-requests'.") (defmacro tramp--test-with-proper-process-name-and-buffer (proc &rest body) "Set \"process-name\" and \"process-buffer\" connection properties. @@ -7116,7 +7145,7 @@ tramp--test-with-proper-process-name-and-buffer (tramp-flush-connection-property v "process-buffer"))))) ;; This test is inspired by Bug#16928. -(ert-deftest tramp-test44-asynchronous-requests () +(ert-deftest tramp-test45-asynchronous-requests () "Check parallel asynchronous requests. Such requests could arrive from timers, process filters and process sentinels. They shall not disturb each other." @@ -7283,7 +7312,7 @@ tramp-test44-asynchronous-requests (unless (process-live-p proc) (setq buffers (delq buf buffers)))))) - ;; Checks. All process output shall exists in the + ;; Checks. All process output shall exist in the ;; respective buffers. All created files shall be ;; deleted. (tramp--test-message "Check %s" (current-time-string)) @@ -7309,10 +7338,10 @@ tramp-test44-asynchronous-requests (ignore-errors (cancel-timer timer)) (ignore-errors (delete-directory tmp-name 'recursive)))))) -;; (tramp--test-deftest-direct-async-process tramp-test44-asynchronous-requests +;; (tramp--test-deftest-direct-async-process tramp-test45-asynchronous-requests ;; 'unstable) -(ert-deftest tramp-test45-dired-compress-file () +(ert-deftest tramp-test46-dired-compress-file () "Check that Tramp (un)compresses normal files." (skip-unless (tramp--test-enabled)) (skip-unless (tramp--test-sh-p)) @@ -7333,7 +7362,7 @@ tramp-test45-dired-compress-file (should (string= tmp-name (dired-get-filename))) (delete-file tmp-name))) -(ert-deftest tramp-test45-dired-compress-dir () +(ert-deftest tramp-test46-dired-compress-dir () "Check that Tramp (un)compresses directories." (skip-unless (tramp--test-enabled)) (skip-unless (tramp--test-sh-p)) @@ -7355,7 +7384,7 @@ tramp-test45-dired-compress-dir (delete-directory tmp-name) (delete-file (concat tmp-name ".tar.gz")))) -(ert-deftest tramp-test46-read-password () +(ert-deftest tramp-test47-read-password () "Check Tramp password handling." :tags '(:expensive-test) (skip-unless (tramp--test-enabled)) @@ -7415,7 +7444,7 @@ tramp-test46-read-password (should (file-exists-p ert-remote-temporary-file-directory))))))))) ;; This test is inspired by Bug#29163. -(ert-deftest tramp-test47-auto-load () +(ert-deftest tramp-test48-auto-load () "Check that Tramp autoloads properly." ;; If we use another syntax but `default', Tramp is already loaded ;; due to the `tramp-change-syntax' call. @@ -7440,7 +7469,7 @@ tramp-test47-auto-load (mapconcat #'shell-quote-argument load-path " -L ") (shell-quote-argument code))))))) -(ert-deftest tramp-test47-delay-load () +(ert-deftest tramp-test48-delay-load () "Check that Tramp is loaded lazily, only when needed." ;; Tramp is neither loaded at Emacs startup, nor when completing a ;; non-Tramp file name like "/foo". Completing a Tramp-alike file @@ -7470,7 +7499,7 @@ tramp-test47-delay-load (mapconcat #'shell-quote-argument load-path " -L ") (shell-quote-argument (format code tm))))))))) -(ert-deftest tramp-test47-recursive-load () +(ert-deftest tramp-test48-recursive-load () "Check that Tramp does not fail due to recursive load." (skip-unless (tramp--test-enabled)) @@ -7494,7 +7523,7 @@ tramp-test47-recursive-load (mapconcat #'shell-quote-argument load-path " -L ") (shell-quote-argument code)))))))) -(ert-deftest tramp-test47-remote-load-path () +(ert-deftest tramp-test48-remote-load-path () "Check that Tramp autoloads its packages with remote `load-path'." ;; `tramp-cleanup-all-connections' is autoloaded from tramp-cmds.el. ;; It shall still work, when a remote file name is in the @@ -7519,7 +7548,7 @@ tramp-test47-remote-load-path (mapconcat #'shell-quote-argument load-path " -L ") (shell-quote-argument code))))))) -(ert-deftest tramp-test48-unload () +(ert-deftest tramp-test49-unload () "Check that Tramp and its subpackages unload completely. Since it unloads Tramp, it shall be the last test to run." :tags '(:expensive-test) @@ -7620,19 +7649,19 @@ tramp-test-all ;; * file-name-case-insensitive-p ;; * memory-info ;; * tramp-get-home-directory -;; * tramp-get-remote-gid -;; * tramp-get-remote-groups -;; * tramp-get-remote-uid ;; * tramp-set-file-uid-gid ;; * Work on skipped tests. Make a comment, when it is impossible. ;; * Revisit expensive tests, once problems in `tramp-error' are solved. ;; * Fix `tramp-test06-directory-file-name' for "ftp". +;; * Check, why a process filter t doesn't work in +;; `tramp-test29-start-file-process' and +;; `tramp-test30-make-process'. ;; * Implement `tramp-test31-interrupt-process' and ;; `tramp-test31-signal-process' for "adb", "sshfs" and for direct ;; async processes. Check, why they don't run stable. ;; * Check, why direct async processes do not work for -;; `tramp-test44-asynchronous-requests'. +;; `tramp-test45-asynchronous-requests'. (provide 'tramp-tests) commit 96015c9c8cc1720e8ee7cd9cea4de48126dd9122 Author: Po Lu Date: Tue Jan 17 18:54:22 2023 +0800 Make tool bar highlight work correctly during touch events * src/xterm.c (handle_one_xevent): Before activating the tool bar in response to a touch event, set the mouse highlight to that location. After the touch ends, clear the mouse highlight. diff --git a/src/xterm.c b/src/xterm.c index 6ae7e97f45a..1373045393a 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -24300,7 +24300,32 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (tool_bar_p) { - handle_tool_bar_click (f, x, y, true, 0); + /* Call note_mouse_highlight on the tool bar + item. Otherwise, get_tool_bar_item will + return 1. + + This is not necessary when mouse-highlight is + nil. */ + + if (!NILP (Vmouse_highlight)) + { + note_mouse_highlight (f, x, y); + + /* Always allow future mouse motion to + update the mouse highlight, no matter + where it is. */ + memset (&dpyinfo->last_mouse_glyph, 0, + sizeof dpyinfo->last_mouse_glyph); + dpyinfo->last_mouse_glyph_frame = f; + } + + handle_tool_bar_click_with_device (f, x, y, true, 0, + (source + ? source->name : Qt)); + + /* Flush any changes made by that to the front + buffer. */ + x_flush_dirty_back_buffer_on (f); /* Record the device and the touch ID on the frame. That way, Emacs knows when to dismiss @@ -24468,8 +24493,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, == xev->detail)) { if (f->last_tool_bar_item != -1) - handle_tool_bar_click (f, xev->event_x, xev->event_y, - false, 0); + handle_tool_bar_click_with_device (f, xev->event_x, + xev->event_y, + false, 0, + (source + ? source->name + : Qnil)); + + /* Cancel any outstanding mouse highlight. */ + note_mouse_highlight (f, -1, -1); + x_flush_dirty_back_buffer_on (f); /* Now clear the tool bar device. */ FRAME_OUTPUT_DATA (f)->tool_bar_touch_device = 0; commit b9025c507a3a7dae4de19b18cafaa09b18183832 Author: Po Lu Date: Tue Jan 17 18:28:37 2023 +0800 Correctly handle touches on the tool bar * src/xterm.c (xi_link_touch_point): New argument `frame'. Set new field `touchpoint->frame' to it. (xi_unlink_touch_points): New function. (xi_disable_devices): Clear the tool bar device on frames whose tool bar device matches this field. (handle_one_xevent): If an XI_TouchBegin event lands on the tool bar, then simulate a pointer click. Ignore future events from that touchpoint from there onwards. (x_make_frame_invisible, x_free_frame_resources): Unlink touch points associated with the frame. * src/xterm.h (struct xi_touch_point_t): New field `frame'. (struct x_output): New fields for keeping track of tool bar touches. diff --git a/src/xterm.c b/src/xterm.c index 028bb7582c4..6ae7e97f45a 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -5750,7 +5750,8 @@ xi_device_from_id (struct x_display_info *dpyinfo, int deviceid) static void xi_link_touch_point (struct xi_device_t *device, - int detail, double x, double y) + int detail, double x, double y, + struct frame *frame) { struct xi_touch_point_t *touchpoint; @@ -5759,6 +5760,7 @@ xi_link_touch_point (struct xi_device_t *device, touchpoint->x = x; touchpoint->y = y; touchpoint->number = detail; + touchpoint->frame = frame; device->touchpoints = touchpoint; } @@ -5787,6 +5789,36 @@ xi_unlink_touch_point (int detail, return false; } +/* Unlink all touch points associated with the frame F. + This is done upon unmapping or destroying F's window, because + touch point delivery after that point is undefined. */ + +static void +xi_unlink_touch_points (struct frame *f) +{ + struct xi_device_t *device; + struct xi_touch_point_t **next, *last; + int i; + + for (i = 0; i < FRAME_DISPLAY_INFO (f)->num_devices; ++i) + { + device = &FRAME_DISPLAY_INFO (f)->devices[i]; + + /* Now unlink all touch points on DEVICE matching F. */ + + for (next = &device->touchpoints; (last = *next);) + { + if (last->frame == f) + { + *next = last->next; + xfree (last); + } + else + next = &last->next; + } + } +} + static struct xi_touch_point_t * xi_find_touch_point (struct xi_device_t *device, int detail) { @@ -13535,6 +13567,10 @@ xi_disable_devices (struct x_display_info *dpyinfo, #ifdef HAVE_XINPUT2_2 struct xi_touch_point_t *tem, *last; #endif +#if defined HAVE_XINPUT2_2 && !defined HAVE_EXT_TOOL_BAR + struct x_output *output; + Lisp_Object tail, frame; +#endif /* Don't pointlessly copy dpyinfo->devices if there are no devices to disable. */ @@ -13577,6 +13613,34 @@ xi_disable_devices (struct x_display_info *dpyinfo, tem = tem->next; xfree (last); } + +#ifndef HAVE_EXT_TOOL_BAR + + /* Now look through each frame on DPYINFO. If it has an + outstanding tool bar press for this device, release + the tool bar. */ + + FOR_EACH_FRAME (tail, frame) + { + if (!FRAME_X_P (XFRAME (frame)) + || (FRAME_DISPLAY_INFO (XFRAME (frame)) + != dpyinfo)) + continue; + + output = FRAME_OUTPUT_DATA (XFRAME (frame)); + + if (output->tool_bar_touch_device + == dpyinfo->devices[i].device_id) + { + if (XFRAME (frame)->last_tool_bar_item != -1 + && WINDOWP (XFRAME (frame)->tool_bar_window)) + handle_tool_bar_click (XFRAME (frame), 0, 0, + false, 0); + + output->tool_bar_touch_device = 0; + } + } +#endif #endif goto out; @@ -24209,6 +24273,48 @@ handle_one_xevent (struct x_display_info *dpyinfo, } #endif +#ifndef HAVE_EXT_TOOL_BAR + /* Is this a touch from a direct touch device that is in + the tool-bar? */ + if (device->direct_p + && WINDOWP (f->tool_bar_window) + && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window))) + { + Lisp_Object window; + int x = xev->event_x; + int y = xev->event_y; + + window = window_from_coordinates (f, x, y, 0, true, true); + /* Ignore button release events if the mouse + wasn't previously pressed on the tool bar. + We do this because otherwise selecting some + text with the mouse and then releasing it on + the tool bar doesn't stop selecting text, + since the tool bar eats the button up + event. */ + tool_bar_p = EQ (window, f->tool_bar_window); + + /* If this touch has started in the tool bar, do not + send it to Lisp. Instead, simulate a tool bar + click, releasing it once it goes away. */ + + if (tool_bar_p) + { + handle_tool_bar_click (f, x, y, true, 0); + + /* Record the device and the touch ID on the + frame. That way, Emacs knows when to dismiss + the tool bar click later. */ + + FRAME_OUTPUT_DATA (f)->tool_bar_touch_device + = device->device_id; + FRAME_OUTPUT_DATA (f)->tool_bar_touch_id = xev->detail; + + goto XI_OTHER; + } + } +#endif + if (!menu_bar_p && !tool_bar_p) { if (f && device->direct_p) @@ -24218,13 +24324,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_catch_errors (dpyinfo->display); if (x_input_grab_touch_events) - XIAllowTouchEvents (dpyinfo->display, xev->deviceid, - xev->detail, xev->event, XIAcceptTouch); + XIAllowTouchEvents (dpyinfo->display, + xev->deviceid, + xev->detail, xev->event, + XIAcceptTouch); if (!x_had_errors_p (dpyinfo->display)) { - xi_link_touch_point (device, xev->detail, xev->event_x, - xev->event_y); + xi_link_touch_point (device, xev->detail, + xev->event_x, + xev->event_y, f); inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT; inev.ie.timestamp = xev->time; @@ -24299,10 +24408,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, for (touchpoint = device->touchpoints; touchpoint; touchpoint = touchpoint->next) { - arg = Fcons (list3i (lrint (touchpoint->x), - lrint (touchpoint->y), - lrint (touchpoint->number)), - arg); + if (touchpoint->frame == f) + arg = Fcons (list3i (lrint (touchpoint->x), + lrint (touchpoint->y), + lrint (touchpoint->number)), + arg); } if (source) @@ -24348,6 +24458,23 @@ handle_one_xevent (struct x_display_info *dpyinfo, } } + /* Now see if the touchpoint was previously on the tool bar. + If it was, release the tool bar. */ + + if (!f) + f = x_window_to_frame (dpyinfo, xev->event); + + if (f && (FRAME_OUTPUT_DATA (f)->tool_bar_touch_id + == xev->detail)) + { + if (f->last_tool_bar_item != -1) + handle_tool_bar_click (f, xev->event_x, xev->event_y, + false, 0); + + /* Now clear the tool bar device. */ + FRAME_OUTPUT_DATA (f)->tool_bar_touch_device = 0; + } + goto XI_OTHER; } @@ -28453,6 +28580,11 @@ x_make_frame_invisible (struct frame *f) block_input (); +#ifdef HAVE_XINPUT2_2 + /* Remove any touch points associated with F. */ + xi_unlink_touch_points (f); +#endif + /* Before unmapping the window, update the WM_SIZE_HINTS property to claim that the current position of the window is user-specified, rather than program-specified, so that when the window is mapped again, it will be @@ -28658,6 +28790,11 @@ x_free_frame_resources (struct frame *f) xi_handle_delete_frame (dpyinfo, f); #endif +#ifdef HAVE_XINPUT2_2 + /* Remove any touch points associated with F. */ + xi_unlink_touch_points (f); +#endif + /* If a display connection is dead, don't try sending more commands to the X server. */ if (dpyinfo->display) diff --git a/src/xterm.h b/src/xterm.h index d768ba7ff8d..28ae00ca190 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -257,10 +257,17 @@ #define MAX_CLIP_RECTS 2 struct xi_touch_point_t { + /* The next touch point in this list. */ struct xi_touch_point_t *next; + /* The touchpoint detail. */ int number; + + /* The last known X and Y position of the touchpoint. */ double x, y; + + /* The frame associated with this touch point. */ + struct frame *frame; }; #endif @@ -1295,6 +1302,16 @@ #define X_ULONG_MAX 0xffffffffUL VisibilityFullyObscured, but is set to something else in handle_one_xevent. */ int visibility_state; + +#ifdef HAVE_XINPUT2_2 + /* The touch ID of the last touch point to have touched the tool + bar. */ + int tool_bar_touch_id; + + /* The device that last touched the tool bar. 0 if no device + touched the tool bar. */ + int tool_bar_touch_device; +#endif }; enum