* Fix for `use-region-p' problem [was: Elisp test for whether `mouse-1' is pressed?] @ 2021-11-07 23:26 Drew Adams 2021-11-08 8:28 ` tomas 0 siblings, 1 reply; 6+ messages in thread From: Drew Adams @ 2021-11-07 23:26 UTC (permalink / raw) To: Emacs developers I got no response to my question of how to tell whether `mouse-1' is still pressed during a click. But I found an answer that seems to work across Emacs releases (24 through 27, the latest I have). Now let me pose a different question/suggestion. I think `use-region-p' does the wrong thing in a particular case, and I suggest a fix for that. Here's the problem I see. Admittedly, most code hasn't, and won't, run into it. `use-region-p' is designed to let code know that either (1) the active region is nonempty or (2) the user has OK'd the use of an empty region (non-nil option `use-empty-active-region'). It should return non-nil in those cases _only_. The problem I've run into comes in #2: empty active region that's declared to be OK to use. I think the real motivation for "use" must be for the user (or some code) to act on the region with the _next_ action - in particular, a user input action - a command. If the region is active and usable then you can act on it - that's the idea. In simple user terms, in this context (being able to act on the active region) a click of `mouse-1' can be considered a single user action. There's no intention, and little ability, for a user to act _between_ the down & up events of a click (as opposed to a drag). (About the only thing a user can do between the down & up events is hit a keyboard key.) I think a user who's OK'd acting on (aka "using") the empty active region really expects that action ("use") to come after the down-&-up click, not between the down & up events. But `use-region-p' is a general test, and it can be used anytime - including between down & up. The current implementation doesn't effectively check whether the region is active and useful for an upcoming user action. If some code tests between down & up, and if the result of that test is shown to a user, then a false impression of "usable" is given - if only momentarily (till the up event). This problem just hasn't been noticed, most likely, because `use-region-p' hasn't been invoked in between those events. My use case is to have the active region - as something that can be acted on by users - be indicated in the mode-line. When active, you see that it's active (you see the region size indicated also, but that's irrelevant here). In particular, OK'ing the use of an empty active region is helpful in this context because you see, in the mode-line, that you're about to act on the empty region - something you typically don't want to do. IOW, this is a way to _see_ ahead of time that you're trying to use an empty region. I use a different user option for this from `use-empty-active-region', and its default value is non-nil. So this feature doesn't interfere with whatever value you prefer for that standard option. But I think the solution I've found (after I posed the question looking for one) should be considered as a fix for the problem in `use-region-p' itself. Why not fix this corner case, even though people aren't very likely to run into it? Here's the code I'd propose: --- (defun use-region-p () "Return non-nil if it is appropriate to act on the region. This is used by commands that act specially on the region when Transient Mark mode is enabled. The return value is non-nil if the region is active and either of the following conditions is true; otherwise, the return value is nil. * The region is nonempty. * Option `use-empty-active-region' is non-nil, and the last input did not use `mouse-1' to set or adjust the region. For some commands, it might be appropriate to ignore the value of `use-empty-active-region'; in that case, use `region-active-p'." (ignore-errors (and (region-active-p) (or (> (region-end) (region-beginning)) (and use-empty-active-region (not (eq 'down-mouse-1 (car-safe last-input-event))) (not (mouse-movement-p last-input-event))))))) --- (The fix ANDs those two mouse conditions to `use-empty-active-region'.) I'm no expert on events, mouse or otherwise, so if someone sees a better implementation, great. (I'm not sure the `ignore-errors' is needed, for example.) The question is really whether preventing `use-region-p' from returning true between the down-&-up events of a click makes sense, and if so, how best to do that. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Fix for `use-region-p' problem [was: Elisp test for whether `mouse-1' is pressed?] 2021-11-07 23:26 Fix for `use-region-p' problem [was: Elisp test for whether `mouse-1' is pressed?] Drew Adams @ 2021-11-08 8:28 ` tomas 2021-11-08 18:32 ` [External] : " Drew Adams 0 siblings, 1 reply; 6+ messages in thread From: tomas @ 2021-11-08 8:28 UTC (permalink / raw) To: emacs-devel [-- Attachment #1: Type: text/plain, Size: 1013 bytes --] On Sun, Nov 07, 2021 at 11:26:45PM +0000, Drew Adams wrote: > I got no response to my question of how to tell > whether `mouse-1' is still pressed during a click. [...] I read twice through your text and I'm still trying to wrap my head around the gist of it. Perhaps that's because I don't use the mouse much (when doing text, at least). Perhaps it's something else. My feeling (it mitght be totally wrong: I'm trying to expound it just in an attempt to debug what's going on) is that you are connecting directly two layers which are too far apart: at the abstract/model/text end selection and its handling, at the concrete/physical/UI end the mouse clicks. In another debugging attempt: could you try to explain what you are up to assuming the user has no mouse? Now the above sounds as if I was trying to imply that you are somehow "wrong". That I am not! I'm just at a loss trying to understand what you are trying and even feel it's difficult for me adequately expressing my difficulties. Cheers - t [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [External] : Re: Fix for `use-region-p' problem [was: Elisp test for whether `mouse-1' is pressed?] 2021-11-08 8:28 ` tomas @ 2021-11-08 18:32 ` Drew Adams 2021-11-09 11:29 ` tomas 0 siblings, 1 reply; 6+ messages in thread From: Drew Adams @ 2021-11-08 18:32 UTC (permalink / raw) To: tomas@tuxteam.de, emacs-devel@gnu.org Thanks for replying, Tomas. > > I got no response to my question of how to tell > > whether `mouse-1' is still pressed during a click. > > [...] > > I read twice through your text and I'm still trying > to wrap my head around the gist of it. Sorry for any confusion or difficulty. I can't tell if you mean that you had difficulty with (1) the original post, asking how to tell when mouse-1 is pressed (the text you quoted) or with (2) my last message (with changed Subject), which is what you replied to. Or perhaps you had difficulty with both? > My feeling (it mitght be totally wrong: I'm trying to expound > it just in an attempt to debug what's going on) is that you > are connecting directly two layers which are too far apart: at > the abstract/model/text end selection and its handling, at the > concrete/physical/UI end the mouse clicks. I can't speak to your feeling or the distinction you describe. You can select text with the mouse (or otherwise) - maybe that's one connection. I have no problem with the abstract behavior of selection, with or without the mouse. And I have no problem with its concrete realization. The problem I described is only with the implementation of predicate `use-region-p'. Its (minor) failing is only with a corner case: returning true between mouse-1 down and up events during a click action (down & up at the same place). When you press mouse-1, drag-tracking is started, so that if you move the mouse across text, that text gets selected. As long as you hold mouse-1 down, tracking continues (well, unless interrupted by some other event such as a keyboard key). Roughly speaking, When you release mouse-1 the selected text is used for the region, and the region/mark is left activated. But if you release mouse-1 at the same place you pressed it, that release (button-up) event deactivates the (empty) region. From a _user_ point of view, when you start to do something just after a click the region is inactive. Your action after a click does _not_ act on an empty active region. This is all as it should be. Event `down-mouse-1' (button-down) activates the region, and event `mouse-1' (button-up) either (1) leaves it activated, if the positions of down & up differ, or (2) deactivates it, if those positions are the same. (See function `mouse-drag-track' for details.) My original question was how to tell whether/when the mouse is tracking. In Emacs 24 (only) I found it was sufficient to test whether `echo-keystrokes' is 0 - a dumb and fragile hack. I was now looking for a better test, one that works across Emacs versions. The better test I came up with, is this: (and (not (eq 'down-mouse-1 (car-safe last-input-event))) (not (mouse-movement-p last-input-event))) That is, whenever the region is empty (and assuming the user OK's empty-region indication), if the last input event wasn't `down-mouse-1' and it wasn't a mouse movement, then it's OK to show the active-region indication in the mode-line. (Not sure why, but apparently if you click mouse-1 on a different frame then the last event after pressing mouse-1 is a mouse movement, not `down-mouse-1'.) That seems to work well in the releases I support for this so far: Emacs 24-27. Maybe it too is fragile and fortuitous, and won't work in Emacs release 42. (Maybe Emacs should provide a predicate for mouse-1 being pressed and not yet released?) > In another debugging attempt: could you try to explain > what you are up to assuming the user has no mouse? If the user has no mouse, or isn't using it in this context, there's no change at all. There's also no effect on dragging the mouse (e.g. selecting text - nonempty region). The behavior to be fixed only involves a mouse-1 click (down & up at the same place). > Now the above sounds as if I was trying to imply that you are > somehow "wrong". That I am not! I'm just at a loss trying to > understand what you are trying and even feel it's difficult for > me adequately expressing my difficulties. I appreciate your response. I hope others will also read what I wrote and speak up. Let me know what else I can add, if something's still unclear. ___ Some more background about my use case, in case it helps or you're interested. (The code is small, in modeline-region.el - see URL below.) Minor mode `modeline-region-mode' shows, in the mode-line, whether the region is active (and some info about its size - various counts etc.). Standard Emacs commands such as search & replace are advised when the mode is on, so that the mode-line indication of the region status makes clear that the current command is actually acting on the region, not the buffer. (The face used is a bit different, to draw attention to this.) Non-nil option `mlr-empty-region-flag' means show the active-region indication in the mode-line even when the region is empty. It's non-nil by default, because being told that you're acting on, or about to act on, the empty region can save you some bother. All of this description applies regardless of how you select text - using the mouse or otherwise. What was problematic, and the problem I wanted to fix, was that if you clicked mouse-1 then an empty region was briefly indicated spuriously. This happened because as soon as you press mouse-1 the region is activated, even though as soon as you release mouse-1 it is deactivated. In this case you momentarily saw, in the mode-line, an indication of an activated empty region. That momentary display (~ a flash) was a bit bothersome. I fixed that. I think the problem is present also for vanilla Emacs, and the same fix makes sense for it. That's what my message now is about: the problem with `use-region-p' and a proposed fix. Admittedly, unless you have some similar use case - continually monitoring and indicating region activation - you won't notice or care about the problem. And yes, if you don't use a mouse then you also won't care about it. I think it's worth it for Emacs to fix this corner case, e.g., have `use-region-p' return nil when the region is empty if mouse-1 is currently still pressed. Why? Because you can't use the active region then, and that's what `use-region-p' is for: saying when you can use the active region. ___ Description: https://www.emacswiki.org/emacs/ModeLineRegion Code: https://www.emacswiki.org/emacs/download/modeline-region.el ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [External] : Re: Fix for `use-region-p' problem [was: Elisp test for whether `mouse-1' is pressed?] 2021-11-08 18:32 ` [External] : " Drew Adams @ 2021-11-09 11:29 ` tomas 2021-11-09 16:17 ` Drew Adams 0 siblings, 1 reply; 6+ messages in thread From: tomas @ 2021-11-09 11:29 UTC (permalink / raw) To: Drew Adams; +Cc: emacs-devel@gnu.org [-- Attachment #1: Type: text/plain, Size: 2839 bytes --] On Mon, Nov 08, 2021 at 06:32:41PM +0000, Drew Adams wrote: > Thanks for replying, Tomas. > > > > I got no response to my question of how to tell > > > whether `mouse-1' is still pressed during a click. > > > > [...] > > > > I read twice through your text and I'm still trying > > to wrap my head around the gist of it. > > Sorry for any confusion or difficulty. Come on. No need to apologise. > I can't tell if you mean that you had difficulty with > (1) the original post, asking how to tell when mouse-1 > is pressed (the text you quoted) or with (2) my last > message (with changed Subject), which is what you > replied to. Or perhaps you had difficulty with both? The direct ref would be (2), but my confusion is so diffuse that I'd take everything with its grain of salt :) > > My feeling (it mitght be totally wrong [...]) [...] > The problem I described is only with the implementation > of predicate `use-region-p'. Its (minor) failing is > only with a corner case: returning true between mouse-1 > down and up events during a click action (down & up at > the same place). Oh, I think I get it now. So I did the following experiment: (setq my-timer (run-with-timer 0 0.05 (lambda() (message "%s REG=%s" (current-time-string) (use-region-p))))) The antidote is: (cancel-timer my-timer) ...I keep it around in the same buffer. Now while the above is running, when I click with mouse-1, REG says "nil" /until/ I move the mouse far enough that the region is at least one char wide: then REG says t. If I go back to the starting point (while keeping mouse-1 down all the time), REG says nil again. I'm not a heavy mouse user (TBH, I'm a reluctant mouse user), but the above behaviour looks reasonable to me. > Event `down-mouse-1' (button-down) activates the region, [...] This doesn't happen for me. I've to drag the mouse a bit for the region to become active (a bit: one char width, as far as I can discern). FWIW, that's "my" Emacs: This is GNU Emacs, one component of the GNU/Linux operating system. GNU Emacs 28.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 2.24.32, cairo version 1.16.0) of 2021-09-30 I haven't tried with -Q, but I would, if you think that might shed more light on the topic. > and event `mouse-1' (button-up) either (1) leaves it > activated, if the positions of down & up differ, or (2) > deactivates it, if those positions are the same. (See > function `mouse-drag-track' for details.) I think we're seeing different things, so there might still be a gap between what I think I've understood and what I've actually understood :) Cheers - t [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [External] : Re: Fix for `use-region-p' problem [was: Elisp test for whether `mouse-1' is pressed?] 2021-11-09 11:29 ` tomas @ 2021-11-09 16:17 ` Drew Adams 2021-11-09 16:58 ` tomas 0 siblings, 1 reply; 6+ messages in thread From: Drew Adams @ 2021-11-09 16:17 UTC (permalink / raw) To: tomas@tuxteam.de; +Cc: emacs-devel@gnu.org > Oh, I think I get it now. So I did the following experiment: > > (setq my-timer > (run-with-timer 0 0.05 > (lambda() > (message "%s REG=%s" > (current-time-string) > (use-region-p))))) ... Cool. Thanks for trying, and looking into it. > Now while the above is running, when I click with mouse-1, REG > says "nil" /until/ I move the mouse far enough that the region > is at least one char wide: then REG says t. If I go back to the > starting point (while keeping mouse-1 down all the time), REG > says nil again. That's exactly right. That's the point of the fix. I know that you're talking about using that recipe _without_ the fix. And you're right, in what you say. But only when option `use-empty-active-region' is nil. The point of the fix is for the behavior you see to be used even if that option is non-nil. Why? Because a click (down&up) always DEactivates the region. A click is a single action, from a user point of view, even though it's realized using two events. There really is no way, normally, to get an empty active region with the mouse - other than keeping mouse-1 pressed. The aim of the fix I proposed is this: if you turn on `use-empty-active-region'. The region won't be considered empty when mouse-1 is still pressed and at the same position. > I'm not a heavy mouse user (TBH, I'm a reluctant mouse user), Many are in the same boat. And that might be an additional reason that this (admittedly corner) case wasn't taken into account before. > but the above behaviour looks reasonable to me. It's the right behavior for both values of `use-empty-active-region', IMO. That's the point. If you happen to agree then there are two of us... ;-) > > Event `down-mouse-1' (button-down) activates the region, > > This doesn't happen for me. I've to drag the mouse a bit for > the region to become active (a bit: one char width, as far as > I can discern). It does happen - see the code. It's just that your recipe to test it uses `use-region-p' (without the fix), and your value of `use-empty-active-region' is nil. Set that option to t and then try your recipe again. > I haven't tried with -Q, but I would, if you think that > might shed more light on the topic. (I used emacs -Q with Emacs 27.) > > and event `mouse-1' (button-up) either (1) leaves it > > activated, if the positions of down & up differ, or (2) > > deactivates it, if those positions are the same. (See > > function `mouse-drag-track' for details.) > > I think we're seeing different things, so there might > still be a gap between what I think I've understood > and what I've actually understood :) I think the gap is just `use-empty-active-region'. Set it to t and try your recipe. That option is for users to tell Emacs how to handle an active empty region. IMO it shouldn't recognize the momentary active empty region that is manifested during a mouse-1 click (down&up at the same location). That's really all there is to what I'm saying/proposing. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [External] : Re: Fix for `use-region-p' problem [was: Elisp test for whether `mouse-1' is pressed?] 2021-11-09 16:17 ` Drew Adams @ 2021-11-09 16:58 ` tomas 0 siblings, 0 replies; 6+ messages in thread From: tomas @ 2021-11-09 16:58 UTC (permalink / raw) To: Drew Adams; +Cc: emacs-devel@gnu.org [-- Attachment #1: Type: text/plain, Size: 1099 bytes --] On Tue, Nov 09, 2021 at 04:17:01PM +0000, Drew Adams wrote: > > Oh, I think I get it now. So I did the following experiment: > > > > (setq my-timer > > (run-with-timer 0 0.05 > > (lambda() > > (message "%s REG=%s" > > (current-time-string) > > (use-region-p))))) > ... > > Cool. Thanks for trying, and looking into it. > > > Now while the above is running, when I click with mouse-1, REG > > says "nil" /until/ I move the mouse far enough that the region > > is at least one char wide: then REG says t. If I go back to the > > starting point (while keeping mouse-1 down all the time), REG > > says nil again. > > That's exactly right. That's the point of the fix. > > I know that you're talking about using that recipe > _without_ the fix. And you're right, in what you say. > > But only when option `use-empty-active-region' is nil. Oh, now I see it, too. Thanks. In this light, I'd think your fix makes sense. Cheers - t [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-11-09 16:58 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2021-11-07 23:26 Fix for `use-region-p' problem [was: Elisp test for whether `mouse-1' is pressed?] Drew Adams 2021-11-08 8:28 ` tomas 2021-11-08 18:32 ` [External] : " Drew Adams 2021-11-09 11:29 ` tomas 2021-11-09 16:17 ` Drew Adams 2021-11-09 16:58 ` tomas
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.