unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: jared--- via "Emacs development discussions." <emacs-devel@gnu.org>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: "jared--- via \"Emacs development discussions.\"" <emacs-devel@gnu.org>
Subject: Re: Additional xterm-mouse cleanup
Date: Tue, 02 Feb 2021 00:24:27 -0800	[thread overview]
Message-ID: <4ab742d461a50a1b9a0debba781a18ad@finder.org> (raw)
In-Reply-To: <jwv4kj1xit5.fsf-monnier+emacs@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 5188 bytes --]

On 2021-01-28 6:25 am, Stefan Monnier wrote:
>> -		     (while (or (memq char (append help-event-list
>> -						   (cons help-char '(?? ?\C-v ?\s ?\177 delete backspace 
>> vertical-scroll-bar ?\M-v))))
>> +                     (while (or (memq (event-basic-type char)
>> +                                      (append help-event-list
>> +                                              (list help-char ?? 
>> ?\C-v ?\s ?\177
>> +                                                    'delete 
>> 'backspace
>> +                                                    
>> 'vertical-scroll-bar
>> +                                                    'mouse-4 'mouse-5 
>> ?\M-v)))
> 
> LGTM, but it would be good to improve the code so it determine this set
> of events automatically, e.g. by looking up local-map or something.

I just went ahead and did a cleanup of the logic around here.  Now 
there's a keymap for all the navigation commands.  Also a simple cache 
of all help characters.  Updated patch attached.

>> Subject: [PATCH 3/4] Support 'mouse-autoselect-window' for GPM and 
>> xterm mouse
> 
> I think this should be consolidated with the *very* similar code in
> `src/msdos.c` and `src/w32inevt.c`.
> 
> [ Ideally it should also be consolidated with the 
> `Vmouse_autoselect_window`
>   support in `src/xterm.c`, `src/nsterm.m`, and `src/w32term.c`.  ]

I completely agree.  However, I don't have access to any of those 
platforms to test against, so I do not feel comfortable making any 
changes.  Instead I added a fixme to all the different locations 
handling mouse movement.  Updated patch attached.

>> The function read_char normally clears the active echo area after
>> reading any event.  When xterm-mouse-mode is active the event can get
>> discarded when input-decode-map is applied (example: a mouse movement
>> escape sequence with 'track-mouse' set to nil) in which case the echo
>> area should stay unchanged.  Other translation keymaps are not
>> intended to ever discard events so the restoring is only done for
>> input-decode-map.
> 
> Actually, I have had translations in `function-key-map` which end up
> discarding the input (and I can't think of any reason why
> `key-translation-map` wouldn't ever want to do that either, other than
> the fact that it's virtually never used).

Okay, this is easy enough to do.  I'll just move the restoration to the 
replay_sequence tag in read_key_sequence.

>>  	  if (done)
>>  	    {
>>  	      mock_input = diff + max (t, mock_input);
>> +
>> +	      /* By this point the echo area was cleared by calls to
>> +		 read_char.  However, we may have completely thrown
>> +		 out the input (for example if decoding a mouse move
>> +		 event but `track-mouse' is nil) in which case the
>> +		 echo area should be restored to its pristene
>> +		 state.  */
>> +	      echo_area_buffer[0] = echo_area_buffer[1];
>>  	      goto replay_sequence;
>>  	    }
> 
> [ Oh ... how I hate that echo area code.  ]
> 
> I think this needs a reproducible test case, ideally one we can run in
> batch as part of our test suite.

I can do this, but I'm not sure what is the right way to test here.  
Best I can see is to use current-message to read the current message 
string, set unread-command-events to simulate key presses, and then call 
read-key-sequence with a timeotu (like how read-key works).  Does this 
sound right?

> Also, I'm curious about a few things:
> - How do we know that the echo area was cleared by calls to 
> `read_char`?
>   [ Do we even know for sure that `read_char` always clears it?  ]

read_char clears the echo area by calling "clear_message (1, 0)" if it 
encounters any event other than help-echo, switch-frame, or 
select-window in normal flow.  See the comment "Now wipe the echo area, 
except for" in read_char.

> - How do we know that this extra line has the effect of restoring it to
>   its pristine state?

Isn't that what echo_area_buffer[1] is for?  See echo_area_display.  I 
could be missing something though, let me know if I have this wrong.  It 
would be easy enough to add a local variable instead for the echo 
message when read_key_sequence is called.

> I think I'd like it better if we could make those things clear in
> the code.  E.g. by having the "code that clears" set some variable
> indicating that it's indeed been cleared and maybe also how it's been
> cleared, and which we can then use here.
> 
> Or alternatively, change the "code that clears" so that it doesn't
> actually clear when called from `read_key_sequence` and let
> `read_key_sequence` take care of clearing the echo area once it has
> *really* read some input?

I don't think these are feasible as read_char's modifications of the 
echo area can be dependent on waiting for user input.  Specifically, it 
echos the dash (via echo_dash) while waiting for input after an idle 
timer activates.  Pulling out read_char's existing code around idle 
timers to control all this will be a beast to pull out.  Additionally, I 
don't see how read_key_sequence could know any better what to do as the 
translation maps are just translating individual character events that 
if typed slowly *should* be echoed.

   -- MJF

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Improve-behavior-for-make-help-screen.patch --]
[-- Type: text/x-diff; name=0001-Improve-behavior-for-make-help-screen.patch, Size: 5445 bytes --]

From 12e442317862f32c35a990290e0fddf1db05d4ff Mon Sep 17 00:00:00 2001
From: Jared Finder <jared@finder.org>
Date: Thu, 3 Dec 2020 22:42:05 -0800
Subject: [PATCH 1/3] Improve behavior for `make-help-screen'

* lisp/help-macro.el (make-help-screen): Don't read just the ESC in a
terminal escape sequence.  Add keymap to control scrolling logic for
help screen.  Then add mouse wheel to that keymap.
---
 lisp/help-macro.el | 75 ++++++++++++++++++++++++----------------------
 1 file changed, 39 insertions(+), 36 deletions(-)

diff --git a/lisp/help-macro.el b/lisp/help-macro.el
index 791b10a878..5197ae496f 100644
--- a/lisp/help-macro.el
+++ b/lisp/help-macro.el
@@ -103,10 +103,14 @@ make-help-screen
 	   (when three-step-help
 	     (message "%s" line-prompt))
 	   (let* ((help-screen (documentation (quote ,doc-fn)))
+                  (help-chars (append (list ?? help-char) help-event-list))
+                  ;; Commands in this map are executed with errors
+                  ;; ignored.
+                  (navigation-map (make-sparse-keymap))
 		  ;; We bind overriding-local-map for very small
 		  ;; sections, *excluding* where we switch buffers
 		  ;; and where we execute the chosen help command.
-		  (local-map (make-sparse-keymap))
+		  (local-map (make-composed-keymap navigation-map ,helped-map))
 		  (new-minor-mode-map-alist minor-mode-map-alist)
 		  (prev-frame (selected-frame))
 		  config new-frame key char)
@@ -117,22 +121,32 @@ make-help-screen
 				    t t help-screen)))
 	     (unwind-protect
 		 (let ((minor-mode-map-alist nil))
-		   (setcdr local-map ,helped-map)
 		   (define-key local-map [t] 'undefined)
-		   ;; Make the scroll bar keep working normally.
-		   (define-key local-map [vertical-scroll-bar]
-		     (lookup-key global-map [vertical-scroll-bar]))
-		   (if three-step-help
-		       (progn
-			 (setq key (let ((overriding-local-map local-map))
-				     (read-key-sequence nil)))
-			 ;; Make the HELP key translate to C-h.
-			 (if (lookup-key function-key-map key)
-			     (setq key (lookup-key function-key-map key)))
-			 (setq char (aref key 0)))
-		     (setq char ??))
-		   (when (or (eq char ??) (eq char help-char)
-			     (memq char help-event-list))
+                   ;; Make terminal escape sequences be fully read.
+                   (define-key local-map "\e" nil)
+
+                   ;; Custom navigation commands.
+                   (dolist (key '("\C-v" "\s"))
+                     (define-key navigation-map key 'scroll-up))
+                   (dolist (key '("\M-v" "\d" [delete] [backspace]))
+                     (define-key navigation-map key 'scroll-down))
+                   ;; Navigation commands that keep working normally.
+                   (dolist (key '(;; Clicks in the scrollbar
+                                  [vertical-scroll-bar]
+                                  ;; Mouse wheel events
+                                  [mouse-4] [mouse-5] [down-mouse-4]
+                                  [down-mouse-5]
+                                  ;; Frame switching
+                                  [switch-frame]))
+                     (define-key navigation-map key
+                       (lookup-key global-map key)))
+
+                   (setq key (if three-step-help
+                                 (let ((overriding-local-map local-map))
+                                   (read-key-sequence-vector nil))
+                               [??])
+                         char (aref key 0))
+		   (when (memq char help-chars)
 		     (setq config (current-window-configuration))
 		     (pop-to-buffer " *Metahelp*" nil t)
 		     (and (fboundp 'make-frame)
@@ -148,32 +162,21 @@ make-help-screen
 		       (help-mode)
 		       (setq new-minor-mode-map-alist minor-mode-map-alist))
 		     (goto-char (point-min))
-		     (while (or (memq char (append help-event-list
-						   (cons help-char '(?? ?\C-v ?\s ?\177 delete backspace vertical-scroll-bar ?\M-v))))
-				(eq (car-safe char) 'switch-frame)
-				(equal key "\M-v"))
-		       (condition-case nil
-			   (cond
-			    ((eq (car-safe char) 'switch-frame)
-			     (handle-switch-frame char))
-			    ((memq char '(?\C-v ?\s))
-			     (scroll-up))
-			    ((or (memq char '(?\177 ?\M-v delete backspace))
-				 (equal key "\M-v"))
-			     (scroll-down)))
-			 (error nil))
+                     (while (or (memq (event-basic-type char) help-chars)
+                                (lookup-key navigation-map key))
+                       (let ((binding (lookup-key navigation-map key)))
+                         (when binding
+                           (condition-case nil
+                               (command-execute binding nil key)
+                             (error nil))))
 		       (let ((cursor-in-echo-area t)
 			     (overriding-local-map local-map))
-			 (setq key (read-key-sequence
+			 (setq key (read-key-sequence-vector
 				    (format "Type one of the options listed%s: "
 					    (if (pos-visible-in-window-p
 						 (point-max))
 						"" ", or SPACE or DEL to scroll")))
-			       char (aref key 0)))
-
-		       ;; If this is a scroll bar command, just run it.
-		       (when (eq char 'vertical-scroll-bar)
-			 (command-execute (lookup-key local-map key) nil key))))
+			       char (aref key 0)))))
 		   ;; We don't need the prompt any more.
 		   (message "")
 		   ;; Mouse clicks are not part of the help feature,
-- 
2.20.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-Support-mouse-autoselect-window-for-GPM-and-xterm-mo.patch --]
[-- Type: text/x-diff; name=0002-Support-mouse-autoselect-window-for-GPM-and-xterm-mo.patch, Size: 4307 bytes --]

From 0219f8e1af24844189b6f3ac3af7f11379fd3a94 Mon Sep 17 00:00:00 2001
From: Jared Finder <jared@finder.org>
Date: Sat, 23 Jan 2021 16:53:43 -0800
Subject: [PATCH 2/3] Support 'mouse-autoselect-window' for GPM and xterm mouse

* src/dispnew.c (update_mouse_position): Generate SELECT_WINDOW_EVENT.
---
 src/dispnew.c  | 32 ++++++++++++++++++++++++++++++--
 src/msdos.c    |  1 +
 src/nsterm.m   |  1 +
 src/w32inevt.c |  1 +
 src/w32term.c  |  1 +
 src/xterm.c    |  1 +
 6 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/src/dispnew.c b/src/dispnew.c
index e603c67136..5dc4ac24db 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3335,11 +3335,39 @@ update_frame_with_menu (struct frame *f, int row, int col)
 int
 update_mouse_position (struct frame *f, int x, int y)
 {
+  int event_count = 0;
+
   previous_help_echo_string = help_echo_string;
   help_echo_string = Qnil;
 
   note_mouse_highlight (f, x, y);
 
+  /* When the mouse moves over a new window, generate a
+     SELECT_WINDOW_EVENT.  */
+  if (!NILP (Vmouse_autoselect_window))
+    {
+      static Lisp_Object last_mouse_window;
+      Lisp_Object window = window_from_coordinates (f, x, y, 0, 0, 0);
+
+      /* Window will be selected only when it is not selected now and
+	 last mouse movement event was not in it.  Minibuffer window
+	 will be selected only when it is active.  */
+      if (WINDOWP (window)
+	  && !EQ (window, last_mouse_window)
+	  && !EQ (window, selected_window))
+	{
+	  struct input_event event;
+	  EVENT_INIT (event);
+	  event.kind = SELECT_WINDOW_EVENT;
+	  event.frame_or_window = window;
+	  kbd_buffer_store_event (&event);
+	  ++event_count;
+	}
+
+      /* Remember the last window where we saw the mouse.  */
+      last_mouse_window = window;
+    }
+
   /* If the contents of the global variable help_echo_string
      has changed, generate a HELP_EVENT.  */
   if (!NILP (help_echo_string)
@@ -3350,10 +3378,10 @@ update_mouse_position (struct frame *f, int x, int y)
 
       gen_help_event (help_echo_string, frame, help_echo_window,
                       help_echo_object, help_echo_pos);
-      return 1;
+      ++event_count;
     }
 
-  return 0;
+  return event_count;
 }
 
 DEFUN ("display--update-for-mouse-movement", Fdisplay__update_for_mouse_movement,
diff --git a/src/msdos.c b/src/msdos.c
index 5da01c9e7c..0dab89d9df 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -2639,6 +2639,7 @@ dos_rawgetc (void)
       /* Check for mouse movement *before* buttons.  */
       mouse_check_moved ();
 
+      /* FIXME: Combine this logic with update_mouse_position.  */
       /* If the mouse moved from the spot of its last sighting, we
          might need to update mouse highlight.  */
       if (mouse_last_x != mouse_prev_x || mouse_last_y != mouse_prev_y)
diff --git a/src/nsterm.m b/src/nsterm.m
index 1b2328628e..60acda1bcd 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -7037,6 +7037,7 @@ - (void) scrollWheel: (NSEvent *)theEvent
 }
 
 
+/* FIXME: Combine this logic with update_mouse_position.  */
 /* Tell emacs the mouse has moved.  */
 - (void)mouseMoved: (NSEvent *)e
 {
diff --git a/src/w32inevt.c b/src/w32inevt.c
index 1a80a00197..383169c3d1 100644
--- a/src/w32inevt.c
+++ b/src/w32inevt.c
@@ -473,6 +473,7 @@ do_mouse_event (MOUSE_EVENT_RECORD *event,
   switch (flags)
     {
     case MOUSE_MOVED:
+      /* FIXME: Combine this logic with update_mouse_position.  */
       {
 	struct frame *f = get_frame ();
 	Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
diff --git a/src/w32term.c b/src/w32term.c
index 0ee805a852..7e9b641414 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -5083,6 +5083,7 @@ w32_read_socket (struct terminal *terminal,
 	  break;
 
 	case WM_MOUSEMOVE:
+	  /* FIXME: Combine this logic with update_mouse_position.  */
 	  /* Ignore non-movement.  */
 	  {
 	    int x = LOWORD (msg.msg.lParam);
diff --git a/src/xterm.c b/src/xterm.c
index 744b80c68a..d9fb389f89 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -8830,6 +8830,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
       goto OTHER;
 
     case MotionNotify:
+      /* FIXME: Combine this logic with update_mouse_position.  */
       {
         x_display_set_last_user_time (dpyinfo, event->xmotion.time);
         previous_help_echo_string = help_echo_string;
-- 
2.20.1


  reply	other threads:[~2021-02-02  8:24 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-28  6:32 Additional xterm-mouse cleanup jared--- via Emacs development discussions.
2021-01-28 14:25 ` Stefan Monnier
2021-02-02  8:24   ` jared--- via Emacs development discussions. [this message]
2021-02-02 14:37     ` Stefan Monnier
2021-02-04  6:54       ` jared--- via Emacs development discussions.
2021-02-15  1:02         ` Jared Finder via Emacs development discussions.
2021-02-25  3:56         ` Stefan Monnier
2021-02-25  6:08           ` Jared Finder via Emacs development discussions.
2021-02-25 13:52             ` Stefan Monnier
2021-01-30  9:38 ` Eli Zaretskii
2021-02-02  8:28   ` jared--- via Emacs development discussions.
2021-02-02 15:08     ` Eli Zaretskii
2021-02-04  6:57       ` jared--- via Emacs development discussions.
2021-02-04 15:04         ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4ab742d461a50a1b9a0debba781a18ad@finder.org \
    --to=emacs-devel@gnu.org \
    --cc=jared@finder.org \
    --cc=monnier@iro.umontreal.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).