unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* transient-mark-mode in 22.0
@ 2005-06-06 17:24 JD Smith
  2005-06-08 12:02 ` Richard Stallman
  0 siblings, 1 reply; 12+ messages in thread
From: JD Smith @ 2005-06-06 17:24 UTC (permalink / raw)



Transient mark mode seems to have changed in behavior between 21.X and
22.x.  I had formerly used it, along with mouse-drag-region, to
temporarily highlight regions of text to operate on.  Binding this to
a down-mouse event, I could mouse-down drag mouse-up and the function
would complete.  Now, mouse-up doesn't seem to do anything, and you
get the "DRAG FINISHED" message only after another event is entered.

Try this in 21.X and 22.X:

(defun do-drag (event)
  "Print value of variable at the mouse position, with `help'"
  (interactive "e")
  (let ((transient-mark-mode t))
    (message "DRAG STARTED")
    (mouse-drag-region event)
    (message "DRAG FINISHED")))

(global-set-key [(control shift down-mouse-2)] 'do-drag)

I noticed that setting the transient-mark-mode variable no longer does
anything, so I attempted:

(defun do-drag (event)
  "Print value of variable at the mouse position, with `help'"
  (interactive "e")
  (transient-mark-mode 1)
  (message "DRAG STARTED")
  (mouse-drag-region event)
  (message "DRAG FINISHED")
  (transient-mark-mode -1))

But that also doesn't finish on mouse-up (and is less than ideal,
since it doesn't restore the existing transient-mark-mode status).

Any suggested workarounds?

Thanks,

JD

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: transient-mark-mode in 22.0
  2005-06-06 17:24 transient-mark-mode in 22.0 JD Smith
@ 2005-06-08 12:02 ` Richard Stallman
  2005-06-08 21:17   ` JD Smith
  0 siblings, 1 reply; 12+ messages in thread
From: Richard Stallman @ 2005-06-08 12:02 UTC (permalink / raw)
  Cc: emacs-devel

    I noticed that setting the transient-mark-mode variable no longer does
    anything

As far as I can see, it still does what it always did.
Did you actually observe that it fails to work?

But I see that the doc string of the variable says that setting it
does nothing.  That doc string is erroneous.

define-minor-mode automatically generates doc strings that say you
can't set the variable directly, and often this is true, but sometimes
it is false.  So I propose the patch below.

Your problem with mouse-up is probably unrelated to this.  I am not
sure whether it is a bug, and I don't have time to look at the issue
now.


*** easy-mmode.el	05 Jun 2005 05:51:44 -0400	1.64
--- easy-mmode.el	08 Jun 2005 07:00:46 -0400	
***************
*** 183,195 ****
  
  	  (let ((curfile (or (and (boundp 'byte-compile-current-file)
  				  byte-compile-current-file)
! 			     load-file-name)))
! 	    `(defcustom ,mode ,init-value
! 	       ,(format "Non-nil if %s is enabled.
  See the command `%s' for a description of this minor-mode.
  Setting this variable directly does not take effect;
! use either \\[customize] or the function `%s'."
! 			pretty-name mode mode)
  	       :set 'custom-set-minor-mode
  	       :initialize 'custom-initialize-default
  	       ,@group
--- 183,201 ----
  
  	  (let ((curfile (or (and (boundp 'byte-compile-current-file)
  				  byte-compile-current-file)
! 			     load-file-name))
! 		base-doc-string)
! 	    (setq base-doc-string "Non-nil if %s is enabled.
  See the command `%s' for a description of this minor-mode.
  Setting this variable directly does not take effect;
! use either \\[customize] or the function `%s'.")
! 	    (if (null body)
! 		(setq base-doc-string "Non-nil if %s is enabled.
! See the command `%s' for a description of this minor-mode."))
! 
! 	    `(defcustom ,mode ,init-value
! 	       (let 
! 	       ,(format base-doc-string pretty-name mode mode)
  	       :set 'custom-set-minor-mode
  	       :initialize 'custom-initialize-default
  	       ,@group

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: transient-mark-mode in 22.0
  2005-06-08 12:02 ` Richard Stallman
@ 2005-06-08 21:17   ` JD Smith
  2005-06-09 14:41     ` Richard Stallman
  2005-06-09 21:39     ` Stefan Monnier
  0 siblings, 2 replies; 12+ messages in thread
From: JD Smith @ 2005-06-08 21:17 UTC (permalink / raw)
  Cc: emacs-devel

On Wed, 2005-06-08 at 08:02 -0400, Richard Stallman wrote:
>     I noticed that setting the transient-mark-mode variable no longer does
>     anything
> 
> As far as I can see, it still does what it always did.
> Did you actually observe that it fails to work?

Only in so far as I expected transient-mark-mode to allow mouse-drag-
region to return upon mouse-up, which it used to do under 21.x.  So in
that sense, it fails to work.  It may well be that all other features of
transient-mark-mode do work when the variable is set.

In Emacs 21.X, when bound to a mouse-down event, this:

(defun do-drag (event)
  (interactive "e")
  (let ((transient-mark-mode t)) ; transient mark
    (message "DRAG STARTED")
    (mouse-drag-region event)
    (message "DRAG FINISHED")))

and this:

(defun do-drag (event)
  (interactive "e")
  (let ((transient-mark-mode nil)) ; no transient-mark
    (message "DRAG STARTED")
    (mouse-drag-region event)
    (message "DRAG FINISHED")))

produce different behavior w.r.t. mouse-up.  In 22.0, they produce the
same behavior.  Unfortunately, it's not the behavior I need.

JD

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: transient-mark-mode in 22.0
  2005-06-08 21:17   ` JD Smith
@ 2005-06-09 14:41     ` Richard Stallman
  2005-06-09 17:54       ` JD Smith
  2005-06-09 21:39     ` Stefan Monnier
  1 sibling, 1 reply; 12+ messages in thread
From: Richard Stallman @ 2005-06-09 14:41 UTC (permalink / raw)
  Cc: emacs-devel

The change you've observed is probably due to a change in the code of
mouse-drag-region.  I suggest you look at the code and see what's
going on.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: transient-mark-mode in 22.0
  2005-06-09 14:41     ` Richard Stallman
@ 2005-06-09 17:54       ` JD Smith
  2005-06-10 22:37         ` Richard Stallman
  0 siblings, 1 reply; 12+ messages in thread
From: JD Smith @ 2005-06-09 17:54 UTC (permalink / raw)
  Cc: emacs-devel

On Thu, 2005-06-09 at 10:41 -0400, Richard Stallman wrote: 
> The change you've observed is probably due to a change in the code of
> mouse-drag-region.  I suggest you look at the code and see what's
> going on.

OK, I've had a look, and think I've figured it out.  Aside from the
superficial difference of having split mouse-drag-region into two
functions in 22.0, the real difference actually occurs in `mouse-show-
mark' which is called after all mouse movement events have been
processed, in the code handling the final up-event of the drag.

In 21.3, mouse-show-mark immediately returns if transient-mark-mode is
set:

(defun mouse-show-mark ()
  (if transient-mark-mode
      (delete-overlay mouse-drag-overlay)
    (let ((inhibit-quit t)
      ....

This allows mouse-drag-region to run to completion.  In 22.0, mouse-
show-mark does *not* return immediately:

(defun mouse-show-mark ()
  (let ((inhibit-quit t)
	(echo-keystrokes 0)
	event events key ignore
	(x-lost-selection-functions
	 (when (boundp 'x-lost-selection-functions)
           (copy-sequence x-lost-selection-functions))))
    (add-hook 'x-lost-selection-functions
	      (lambda (seltype)
		(when (eq seltype 'PRIMARY)
                  (setq ignore t)
                  (throw 'mouse-show-mark t))))
    (if transient-mark-mode
	(delete-overlay mouse-drag-overlay)
      (move-overlay mouse-drag-overlay (point) (mark t)))
    (catch 'mouse-show-mark
      ;; In this loop, execute scroll bar and switch-frame events.
      ;; Should we similarly handle `select-window' events?  --Stef
      ;; Also ignore down-events that are undefined.
      (while (progn (setq event (read-event))
        ....

Instead, it waits for that final read-event, apparently relating to
scrollbar/frame events.  So it essentially requires one last non-drag
event (arrow movement, anything), to permit mouse-drag-region to run to
completion.

It *could* be that this is a bug introduced when mouse-show-mark was
rearranged, and what was intended was really:

    (if transient-mark-mode
	(delete-overlay mouse-drag-overlay)
      (move-overlay mouse-drag-overlay (point) (mark t))
      (catch 'mouse-show-mark
	;; In this loop, execute scroll bar and switch-frame events.
	;; Should we similarly handle `select-window' events?  --Stef
	;; Also ignore down-events that are undefined.
        ....

i.e. the loop is never entered and read-event is never called, if
transient-mark-mode is set.  This trivial fix gives me the behavior I
want, but since I don't know enough about these functions to understand
if this was intended behavior or not, I'd appreciate your feedback.

Here is the relevant change log comment:

revision 1.252
date: 2004/10/27 17:44:59;  author: rms;  state: Exp;  lines: +49 -48
(mouse-show-mark): Do most processing the same
regardless of transient-mark-mode.

>From the comment it does seem intended.  

JD

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: transient-mark-mode in 22.0
  2005-06-08 21:17   ` JD Smith
  2005-06-09 14:41     ` Richard Stallman
@ 2005-06-09 21:39     ` Stefan Monnier
  1 sibling, 0 replies; 12+ messages in thread
From: Stefan Monnier @ 2005-06-09 21:39 UTC (permalink / raw)
  Cc: rms, emacs-devel

>> I noticed that setting the transient-mark-mode variable no longer does
>> anything
>> 
>> As far as I can see, it still does what it always did.
>> Did you actually observe that it fails to work?

> Only in so far as I expected transient-mark-mode to allow mouse-drag-
> region to return upon mouse-up, which it used to do under 21.x.  So in
> that sense, it fails to work.  It may well be that all other features of
> transient-mark-mode do work when the variable is set.

> In Emacs 21.X, when bound to a mouse-down event, this:

> (defun do-drag (event)
>   (interactive "e")
>   (let ((transient-mark-mode t)) ; transient mark
>     (message "DRAG STARTED")
>     (mouse-drag-region event)
>     (message "DRAG FINISHED")))

> and this:

> (defun do-drag (event)
>   (interactive "e")
>   (let ((transient-mark-mode nil)) ; no transient-mark
>     (message "DRAG STARTED")
>     (mouse-drag-region event)
>     (message "DRAG FINISHED")))

> produce different behavior w.r.t. mouse-up.  In 22.0, they produce the
> same behavior.  Unfortunately, it's not the behavior I need.

I believe this is due to the change

   revision 1.252
   date: 2004/10/27 17:44:59;  author: rms;  state: Exp;  lines: +49 -48
   (mouse-show-mark): Do most processing the same
   regardless of transient-mark-mode.
   ----------------------------

This code in mouse-show-mark is also responsible for the problem where
flyspell's mouse-2 also does a yank, reported a while back, and probably
a few other similar bug reports.  Before 1.252 the problem was only
affecting users who don't use transient-mark-mode.

To fix this problem, I maybe mouse-show-mark should be rewritten to not use
(read-event), but instead to use something like pre-command-hook.

Looking at the code of mouse-show-mark, it's pretty messed up:

- in the code below,

	(and (consp event)
	     (or (eq (car event) 'switch-frame)
		 (eq (posn-point (event-end event))
		     'vertical-scroll-bar))
	     (let ((keys (vector 'vertical-scroll-bar event)))
	       (and (key-binding keys)
		    (progn
		      (call-interactively (key-binding keys)
					  nil keys)
		      (setq events nil)))))))

  if the event is `switch-frame', we'll do a key lookup for
  [vertical-scroll-bar switch-frame] which of course will fail.

- since the while loop is expected to execute code such as
  handle-switch-frame (which it luckily doesn't), the selected buffer might
  get changed before we reach the end where we do (delete-region (mark t)
  (point)), so if we fix the above error, we bump into another.

- the overlay management has apparently been rendered completely useless by
  the use of the temporary transient-mark-mode.  So all that this code
  really does is implement the mouse-region-delete-keys.  This variable was
  introduced in 1996, but is not documented anywhere.  Does anybody use
  this?  (I expect that people who want such a functionality probably use
  delete-selection-mode instead anyway).  I.e. if could drop
  mouse-region-delete-keys, then we could completely remove mouse-show-mark
  and the associated bugs.


        Stefan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: transient-mark-mode in 22.0
  2005-06-09 17:54       ` JD Smith
@ 2005-06-10 22:37         ` Richard Stallman
  2005-06-10 22:49           ` JD Smith
  2005-06-12 16:09           ` Stefan Monnier
  0 siblings, 2 replies; 12+ messages in thread
From: Richard Stallman @ 2005-06-10 22:37 UTC (permalink / raw)
  Cc: emacs-devel

    It *could* be that this is a bug introduced when mouse-show-mark was
    rearranged, and what was intended was really:

	(if transient-mark-mode
	    (delete-overlay mouse-drag-overlay)
	  (move-overlay mouse-drag-overlay (point) (mark t))

I recall making that change intentionally, and the change log entry
confirms it.

I did this to fix a bug.  I don't remember what bug, but It may have
had to do with the new features that temporarily enable
transient-mark-mode.

So I guess you're out of luck on this one.

Stefan wrote:

    To fix this problem, I maybe mouse-show-mark should be rewritten to not use
    (read-event), but instead to use something like pre-command-hook.

I think that is too risky.  The reason this code has some bugs
is that there is no obvious simple rule for what it should do.
I could only patch it case by case, as various cases showed up
that did not work.

If you rewrite it to work differently, you'll have to start this
process from scratch, which means it will be more unstable than
it is now.

      if the event is `switch-frame', we'll do a key lookup for
      [vertical-scroll-bar switch-frame] which of course will fail.

Does that lead to the wrong results?

    - the overlay management has apparently been rendered completely useless by
      the use of the temporary transient-mark-mode.  So all that this code
      really does is implement the mouse-region-delete-keys.  This variable was
      introduced in 1996, but is not documented anywhere.

We must have forgotten to document the feature.  However, the feature
is not just this variable.  The feature is that typing DELETE deletes
the selected region.

It isn't documented, but I would expect that many people have simply
tried it, expecting it to work, and found that it did, so they use it.

							   Does anybody use
      this?  (I expect that people who want such a functionality probably use
      delete-selection-mode instead anyway).

They might; but it isn't exactly the same, and it would not surprise
me if many users use this feature and don't use delete-selection-mode.
Perhaps they would be happy switching to delete-selection-mode, but it
is not obvious.

However, if the only function of that code is to implement this
feature, it might easy to reimplement the feature in a simpler way.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: transient-mark-mode in 22.0
  2005-06-10 22:37         ` Richard Stallman
@ 2005-06-10 22:49           ` JD Smith
  2005-06-11 23:16             ` Richard Stallman
  2005-06-12 16:29             ` Stefan Monnier
  2005-06-12 16:09           ` Stefan Monnier
  1 sibling, 2 replies; 12+ messages in thread
From: JD Smith @ 2005-06-10 22:49 UTC (permalink / raw)
  Cc: emacs-devel

On Fri, 2005-06-10 at 18:37 -0400, Richard Stallman wrote:
>     It *could* be that this is a bug introduced when mouse-show-mark was
>     rearranged, and what was intended was really:
> 
> 	(if transient-mark-mode
> 	    (delete-overlay mouse-drag-overlay)
> 	  (move-overlay mouse-drag-overlay (point) (mark t))
> 
> I recall making that change intentionally, and the change log entry
> confirms it.
> 
> I did this to fix a bug.  I don't remember what bug, but It may have
> had to do with the new features that temporarily enable
> transient-mark-mode.
> 
> So I guess you're out of luck on this one.

So does anyone besides me see it as a problem that mouse-drag-region
does not return when the mouse drag is complete, but instead requires
yet another event of some kind (any kind) after the mouse-up to let it
return?  Is that not a new bug?  That functionality was really what was
behind my use of transient-mark-mode.

If that's really now an impossibility, can anyone recommend another
method to allow a region to be mouse-dragged with highlighting, and a
menu popped up upon drag completion?

JD

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: transient-mark-mode in 22.0
  2005-06-10 22:49           ` JD Smith
@ 2005-06-11 23:16             ` Richard Stallman
  2005-06-12 16:29             ` Stefan Monnier
  1 sibling, 0 replies; 12+ messages in thread
From: Richard Stallman @ 2005-06-11 23:16 UTC (permalink / raw)
  Cc: emacs-devel

    So does anyone besides me see it as a problem that mouse-drag-region
    does not return when the mouse drag is complete, but instead requires
    yet another event of some kind (any kind) after the mouse-up to let it
    return?  Is that not a new bug?

That function's is to implement the mouse click.  Other uses are
not part of its purpose, and I would not want to risk rewriting it
merely for the sake of other uses.

However, Stefan has an idea for simplification that might be ok.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: transient-mark-mode in 22.0
  2005-06-10 22:37         ` Richard Stallman
  2005-06-10 22:49           ` JD Smith
@ 2005-06-12 16:09           ` Stefan Monnier
  2005-06-13 15:02             ` Richard Stallman
  1 sibling, 1 reply; 12+ messages in thread
From: Stefan Monnier @ 2005-06-12 16:09 UTC (permalink / raw)
  Cc: emacs-devel, JD Smith

>     To fix this problem, I maybe mouse-show-mark should be rewritten to
>     not use (read-event), but instead to use something like
>     pre-command-hook.

> I think that is too risky.  The reason this code has some bugs
> is that there is no obvious simple rule for what it should do.
> I could only patch it case by case, as various cases showed up
> that did not work.

> If you rewrite it to work differently, you'll have to start this
> process from scratch, which means it will be more unstable than
> it is now.

No, the current code and the change-log-trail make it pretty clear what the
function is meant to do:
1 - preserve the mouse-drag-overlay highlighting until the "next" command,
    where things like scrolls and switch-frames aren't considered
    real commands.
2 - implement the mouse-region-delete-keys functionality.

The problem is that the loop that does
read-event/key-binding/call-interactively basically can't be reliably
re-implemented in elisp.  That's why a solution using pre-command-hook would
probably be more reliable.

>       if the event is `switch-frame', we'll do a key lookup for
>       [vertical-scroll-bar switch-frame] which of course will fail.
> Does that lead to the wrong results?

It don't know of any bug it introduces but since it fails to call
handle-switch-frame at the proper time, I guess reading the code of
handle-switch-frame should make it reasonably easy to come up with
a scenario where it doesn't do the right thing.

>     - the overlay management has apparently been rendered completely
>     useless by the use of the temporary transient-mark-mode.  So all that
>     this code really does is implement the mouse-region-delete-keys.
>     This variable was introduced in 1996, but is not documented anywhere.

> We must have forgotten to document the feature.  However, the feature
> is not just this variable.  The feature is that typing DELETE deletes
> the selected region.

That's what I meant by the "mouse-region-delete-keys" feature, of course.

> It isn't documented, but I would expect that many people have simply
> tried it, expecting it to work, and found that it did, so they use it.

Could be.

> 							   Does anybody use
>       this?  (I expect that people who want such a functionality probably use
>       delete-selection-mode instead anyway).

> They might; but it isn't exactly the same, and it would not surprise
> me if many users use this feature and don't use delete-selection-mode.
> Perhaps they would be happy switching to delete-selection-mode, but it
> is not obvious.

> However, if the only function of that code is to implement this
> feature, it might easy to reimplement the feature in a simpler way.

Indeed.


        Stefan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: transient-mark-mode in 22.0
  2005-06-10 22:49           ` JD Smith
  2005-06-11 23:16             ` Richard Stallman
@ 2005-06-12 16:29             ` Stefan Monnier
  1 sibling, 0 replies; 12+ messages in thread
From: Stefan Monnier @ 2005-06-12 16:29 UTC (permalink / raw)
  Cc: rms, emacs-devel

> So does anyone besides me see it as a problem that mouse-drag-region
> does not return when the mouse drag is complete, but instead requires
> yet another event of some kind (any kind) after the mouse-up to let it
> return?  Is that not a new bug?  That functionality was really what was
> behind my use of transient-mark-mode.

> If that's really now an impossibility, can anyone recommend another
> method to allow a region to be mouse-dragged with highlighting, and a
> menu popped up upon drag completion?

I agree with you that Emacs should have a function similar to XEmacs's
mouse-track and that your (let ((transient-mark-mode t))
(mouse-drag-region)) was a pretty good approximation of it, which
Emacs-22 breaks.

But I also agree with Richard that the solution is probably not to change
mouse-drag-region to do what you want.  After all mouse-drag-region is
a command which does many predefined things which you don't want, whereas
you only want a function that does "one" particular thing.

Maybe you should try and restructure mouse-drag-region so as to define a new
function, used by mouse-drag-region and that you could also use for your
own purposes.  You may want to check holes.el which also needs something
like that.

I guess the function could begin something like the following:

  (defun mouse-drag-loop ()
    "Track mouse movements while highlighting the region.
  Maintain the region between point and the mouse's position highlighted,
  until some non-motion event.
  Return the event that caused the loop to exit."

Most of the code can be extracted from mouse-drag-region-1.


        Stefan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: transient-mark-mode in 22.0
  2005-06-12 16:09           ` Stefan Monnier
@ 2005-06-13 15:02             ` Richard Stallman
  0 siblings, 0 replies; 12+ messages in thread
From: Richard Stallman @ 2005-06-13 15:02 UTC (permalink / raw)
  Cc: emacs-devel, jdsmith

    > However, if the only function of that code is to implement this
    > feature, it might easy to reimplement the feature in a simpler way.

    Indeed.

Feel free to give it a try.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2005-06-13 15:02 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-06-06 17:24 transient-mark-mode in 22.0 JD Smith
2005-06-08 12:02 ` Richard Stallman
2005-06-08 21:17   ` JD Smith
2005-06-09 14:41     ` Richard Stallman
2005-06-09 17:54       ` JD Smith
2005-06-10 22:37         ` Richard Stallman
2005-06-10 22:49           ` JD Smith
2005-06-11 23:16             ` Richard Stallman
2005-06-12 16:29             ` Stefan Monnier
2005-06-12 16:09           ` Stefan Monnier
2005-06-13 15:02             ` Richard Stallman
2005-06-09 21:39     ` Stefan Monnier

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).