* mouse-drag-and-drop-region @ 2017-11-14 9:54 martin rudalics 2017-11-14 17:01 ` mouse-drag-and-drop-region Eli Zaretskii ` (2 more replies) 0 siblings, 3 replies; 89+ messages in thread From: martin rudalics @ 2017-11-14 9:54 UTC (permalink / raw) To: emacs-devel, tak.kunihiro Sorry for reacting late to the addition of ‘mouse-drag-and-drop-region’ but it never worked with multiple windows here so I had to find the source of that problem first. It turned out that having ‘mouse-autoselect-window’ non-nil interferes, because whenever the mouse enters another window, a 'select-window' event will be generated which the code should ignore. I now installed the necessary change. The code should ignore ‘switch-frame’ events too. But this won't accomplish much at the moment because to drag text from one frame to another we need additional provisions. In principle, Emacs should always avoid switching frames during and after mouse tracking but I'm not yet sure how to do that consistently. Anyway, here are some comments: (1) Why does the value selection happen within the ‘track-mouse’ form and why do you delete the mouse overlay? That is, why don't we move this part (unless value-selection ; initialization (delete-overlay mouse-secondary-overlay) (setq value-selection (buffer-substring start end)) (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) right to the beginning so we have something like (let* ((start (region-beginning)) (end (region-end)) (point (point)) (buffer (current-buffer)) (window (selected-window)) (value-selection (buffer-substring start end))) (move-overlay mouse-secondary-overlay start end) (track-mouse ... there? (2) Activating the secondary overlay can be distracting and should be made optional (facultatively keeping the primary overlay in place provided (4) below is done). (3) Showing tooltips can be distracting and should be optional. Note also, that usurping tooltips this way may prevent them from showing interesting properties of the drop area like whether the text there is read only. OTOH we might consider retaining properties of the text in (non-GTK) tooltips. (4) The (deactivate-mark) and (mouse-set-point event) trick to allow showing point the way ‘mouse-drag-track’ does can be distracting and should be made optional. (5) The mouse pointer shape should take care of indicating the exact position where the drop occurs. We should probably also signal whenever the current drop position is invalid. This is IIUC usual practice on most window systems now. (6) Dropping should allow to copy text into the region itself. There's no reason forbidding that. (7) IMO either cutting should be the default too when the drop occurs in a different buffer or copying would be the default and pressing the modifier should produce a cut instead. The current behavior wants me to always keep in mind whether the target buffer is the same as the source buffer. At least, this behavior should be made optional. (8) Read-only text should be handled. An attempt to drop text into a read-only area should be signalled to the user. An attempt to cut text from a read-only text/buffer should be signalled as well. (9) The code must become resilient against any failures by wrapping it into a ‘condition-case’ and doing the necessary clean up operations (restoring region and point, deleting the secondary overlay). I think (8) and (9) should be fixed before the release. As for future releases we might also consider a ‘set-transient-map’ based solution. Sincerely, martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-14 9:54 mouse-drag-and-drop-region martin rudalics @ 2017-11-14 17:01 ` Eli Zaretskii 2017-11-14 18:29 ` mouse-drag-and-drop-region martin rudalics 2017-11-14 20:17 ` mouse-drag-and-drop-region Alex 2017-11-16 0:28 ` mouse-drag-and-drop-region Tak Kunihiro 2 siblings, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-14 17:01 UTC (permalink / raw) To: martin rudalics; +Cc: tak.kunihiro, emacs-devel > Date: Tue, 14 Nov 2017 10:54:09 +0100 > From: martin rudalics <rudalics@gmx.at> > > (8) Read-only text should be handled. An attempt to drop text into a > read-only area should be signalled to the user. An attempt to cut > text from a read-only text/buffer should be signalled as well. For the latter, we copy text instead (cf C-w in read-only text). So I think this feature should behave similarly, at least by default. Thanks for the review. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-14 17:01 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-14 18:29 ` martin rudalics 0 siblings, 0 replies; 89+ messages in thread From: martin rudalics @ 2017-11-14 18:29 UTC (permalink / raw) To: Eli Zaretskii; +Cc: tak.kunihiro, emacs-devel >> (8) Read-only text should be handled. An attempt to drop text into a >> read-only area should be signalled to the user. An attempt to cut >> text from a read-only text/buffer should be signalled as well. > > For the latter, we copy text instead (cf C-w in read-only text). So I > think this feature should behave similarly, at least by default. I just noticed that the code does use ‘kill-region’ already. This has the side-effect of putting the text into the kill ring, something which should be documented at least. But I think the code should rather use ‘delete-region’ instead with the behavior you proposed. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-14 9:54 mouse-drag-and-drop-region martin rudalics 2017-11-14 17:01 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-14 20:17 ` Alex 2017-11-15 9:22 ` mouse-drag-and-drop-region martin rudalics 2017-11-15 20:22 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-16 0:28 ` mouse-drag-and-drop-region Tak Kunihiro 2 siblings, 2 replies; 89+ messages in thread From: Alex @ 2017-11-14 20:17 UTC (permalink / raw) To: martin rudalics; +Cc: Eli Zaretskii, tak.kunihiro, emacs-devel martin rudalics <rudalics@gmx.at> writes: > Anyway, here are some comments: > > (1) Why does the value selection happen within the ‘track-mouse’ form > and why do you delete the mouse overlay? That is, why don't we move > this part > > (unless value-selection ; initialization > (delete-overlay mouse-secondary-overlay) > (setq value-selection (buffer-substring start end)) > (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) > > right to the beginning so we have something like > > (let* ((start (region-beginning)) > (end (region-end)) > (point (point)) > (buffer (current-buffer)) > (window (selected-window)) > (value-selection (buffer-substring start end))) > (move-overlay mouse-secondary-overlay start end) > (track-mouse > ... > > there? I imagine that this has to do with inputting a non-mouse-movement event before moving the mouse at all. If you use your change and press "C-g" before moving the mouse, then the region will still be pasted. Doing the above without your change currently results in an error due to `insert' using a nil `value-selection', though. So it's faulty either way. > (3) Showing tooltips can be distracting and should be optional. Note > also, that usurping tooltips this way may prevent them from showing > interesting properties of the drop area like whether the text there > is read only. OTOH we might consider retaining properties of the > text in (non-GTK) tooltips. Also, trying to use `tooltip-show' in text-terminals using `xterm-mouse-mode' yields a lot of "Error while displaying tooltip" messages. > I think (8) and (9) should be fixed before the release. As for future > releases we might also consider a ‘set-transient-map’ based solution. Perhaps (3) should be fixed before release as well (at least disabling tooltips when they can't be shown)? Eli, would it be okay to make the same `read-event' -> `read-key' change (specific to xt-mouse as in Bug#29150) here as well to tide over until the function uses `set-transient-map'? This appears to be the last `read-event' present in mouse.el to get rid of. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-14 20:17 ` mouse-drag-and-drop-region Alex @ 2017-11-15 9:22 ` martin rudalics 2017-11-15 18:22 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-15 19:46 ` mouse-drag-and-drop-region Alex 2017-11-15 20:22 ` mouse-drag-and-drop-region Eli Zaretskii 1 sibling, 2 replies; 89+ messages in thread From: martin rudalics @ 2017-11-15 9:22 UTC (permalink / raw) To: Alex; +Cc: Eli Zaretskii, tak.kunihiro, emacs-devel > I imagine that this has to do with inputting a non-mouse-movement event > before moving the mouse at all. If you use your change and press "C-g" > before moving the mouse, then the region will still be pasted. > > Doing the above without your change currently results in an error due to > `insert' using a nil `value-selection', though. So it's faulty either > way. I'm missing you. Doesn't C-g deactivate the mark? >> (3) Showing tooltips can be distracting and should be optional. Note >> also, that usurping tooltips this way may prevent them from showing >> interesting properties of the drop area like whether the text there >> is read only. OTOH we might consider retaining properties of the >> text in (non-GTK) tooltips. > > Also, trying to use `tooltip-show' in text-terminals using > `xterm-mouse-mode' yields a lot of "Error while displaying tooltip" > messages. That's a plain bug. ‘tooltip-show’ on a text terminal must use the echo area. > Perhaps (3) should be fixed before release as well (at least disabling > tooltips when they can't be shown)? Sure. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-15 9:22 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-15 18:22 ` Eli Zaretskii 2017-11-15 18:50 ` mouse-drag-and-drop-region martin rudalics 2017-11-15 19:46 ` mouse-drag-and-drop-region Alex 1 sibling, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-15 18:22 UTC (permalink / raw) To: martin rudalics; +Cc: tak.kunihiro, agrambot, emacs-devel > Date: Wed, 15 Nov 2017 10:22:45 +0100 > From: martin rudalics <rudalics@gmx.at> > Cc: Eli Zaretskii <eliz@gnu.org>, tak.kunihiro@gmail.com, > emacs-devel <emacs-devel@gnu.org> > > > Also, trying to use `tooltip-show' in text-terminals using > > `xterm-mouse-mode' yields a lot of "Error while displaying tooltip" > > messages. > > That's a plain bug. ‘tooltip-show’ on a text terminal must use the echo > area. It does, if you invoke it with 2nd argument non-nil. It's not a bug, it's the intended behavior. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-15 18:22 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-15 18:50 ` martin rudalics 2017-11-15 20:01 ` mouse-drag-and-drop-region Eli Zaretskii 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-11-15 18:50 UTC (permalink / raw) To: Eli Zaretskii; +Cc: tak.kunihiro, agrambot, emacs-devel >> That's a plain bug. ‘tooltip-show’ on a text terminal must use the echo >> area. > > It does, if you invoke it with 2nd argument non-nil. > > It's not a bug, it's the intended behavior. It's a bug in 'mouse-drag-and-drop-region' obviously. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-15 18:50 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-15 20:01 ` Eli Zaretskii 2017-11-16 9:04 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-15 20:01 UTC (permalink / raw) To: martin rudalics; +Cc: tak.kunihiro, agrambot, emacs-devel > Date: Wed, 15 Nov 2017 19:50:26 +0100 > From: martin rudalics <rudalics@gmx.at> > CC: tak.kunihiro@gmail.com, agrambot@gmail.com, emacs-devel@gnu.org > > >> That's a plain bug. ‘tooltip-show’ on a text terminal must use the echo > >> area. > > > > It does, if you invoke it with 2nd argument non-nil. > > > > It's not a bug, it's the intended behavior. > > It's a bug in 'mouse-drag-and-drop-region' obviously. Right. (I think it shouldn't show a tip on TTY frames, not in the echo area, not anywhere.) ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-15 20:01 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-16 9:04 ` martin rudalics 0 siblings, 0 replies; 89+ messages in thread From: martin rudalics @ 2017-11-16 9:04 UTC (permalink / raw) To: Eli Zaretskii; +Cc: tak.kunihiro, agrambot, emacs-devel > Right. (I think it shouldn't show a tip on TTY frames, not in the > echo area, not anywhere.) Agreed. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-15 9:22 ` mouse-drag-and-drop-region martin rudalics 2017-11-15 18:22 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-15 19:46 ` Alex 2017-11-15 20:15 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-16 9:04 ` mouse-drag-and-drop-region martin rudalics 1 sibling, 2 replies; 89+ messages in thread From: Alex @ 2017-11-15 19:46 UTC (permalink / raw) To: martin rudalics; +Cc: Eli Zaretskii, tak.kunihiro, emacs-devel martin rudalics <rudalics@gmx.at> writes: >> I imagine that this has to do with inputting a non-mouse-movement event >> before moving the mouse at all. If you use your change and press "C-g" >> before moving the mouse, then the region will still be pasted. >> >> Doing the above without your change currently results in an error due to >> `insert' using a nil `value-selection', though. So it's faulty either >> way. > > I'm missing you. Doesn't C-g deactivate the mark? Usually, but I don't think it does in this case. To be clear, it's not just C-g that does this. Here's a recipe: 1. Select a region. 2. Hold down-mouse-1 inside of this region. 3. Press any key before moving or releasing the mouse. Doing this yields an error without your change, and it pastes the region with your change. Even when this key is C-g, `mark-active' is t after step 3. >>> (3) Showing tooltips can be distracting and should be optional. Note >>> also, that usurping tooltips this way may prevent them from showing >>> interesting properties of the drop area like whether the text there >>> is read only. OTOH we might consider retaining properties of the >>> text in (non-GTK) tooltips. >> >> Also, trying to use `tooltip-show' in text-terminals using >> `xterm-mouse-mode' yields a lot of "Error while displaying tooltip" >> messages. > > That's a plain bug. ‘tooltip-show’ on a text terminal must use the echo > area. > >> Perhaps (3) should be fixed before release as well (at least disabling >> tooltips when they can't be shown)? > > Sure. I suppose (display-graphic-p) should be supplied as the 2nd argument to `tooltip-show', then? I also noticed that when dragging in an X window, the tooltip flickers quite a bit. Is there any easy remedy for this? Removing the `mouse-set-point' call in `track-mouse' helps in some cases, but not completely. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-15 19:46 ` mouse-drag-and-drop-region Alex @ 2017-11-15 20:15 ` Eli Zaretskii 2017-11-15 22:03 ` mouse-drag-and-drop-region Alex 2017-11-16 9:04 ` mouse-drag-and-drop-region martin rudalics 1 sibling, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-15 20:15 UTC (permalink / raw) To: Alex; +Cc: rudalics, tak.kunihiro, emacs-devel > From: Alex <agrambot@gmail.com> > Cc: Eli Zaretskii <eliz@gnu.org>, tak.kunihiro@gmail.com, emacs-devel <emacs-devel@gnu.org> > Date: Wed, 15 Nov 2017 13:46:42 -0600 > > I suppose (display-graphic-p) should be supplied as the 2nd argument to > `tooltip-show', then? display-multi-frame-p is more appropriate. But I think the tooltip should not be shown at all on TTY frames, it looks unnecessary and even silly to show the dragged text in the echo area. > I also noticed that when dragging in an X window, the tooltip flickers > quite a bit. Is there any easy remedy for this? We constantly redisplay the tooltip frame, don't we? Or does this happen only with GTK tooltips? ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-15 20:15 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-15 22:03 ` Alex 2017-11-16 15:54 ` mouse-drag-and-drop-region Eli Zaretskii 0 siblings, 1 reply; 89+ messages in thread From: Alex @ 2017-11-15 22:03 UTC (permalink / raw) To: Eli Zaretskii; +Cc: rudalics, tak.kunihiro, emacs-devel Eli Zaretskii <eliz@gnu.org> writes: >> From: Alex <agrambot@gmail.com> >> Cc: Eli Zaretskii <eliz@gnu.org>, tak.kunihiro@gmail.com, emacs-devel <emacs-devel@gnu.org> >> Date: Wed, 15 Nov 2017 13:46:42 -0600 >> >> I suppose (display-graphic-p) should be supplied as the 2nd argument to >> `tooltip-show', then? > > display-multi-frame-p is more appropriate. That appears to be an alias to `display-graphic-p'. > But I think the tooltip should not be shown at all on TTY frames, it > looks unnecessary and even silly to show the dragged text in the echo > area. That sounds better. Though I wonder if tooltips could be shown in TTY frames using a method similar to how `x-popup-menu' displays a menu in them? >> I also noticed that when dragging in an X window, the tooltip flickers >> quite a bit. Is there any easy remedy for this? > > We constantly redisplay the tooltip frame, don't we? Or does this > happen only with GTK tooltips? I don't know the details, but it appears that there are some redisplay cycles that don't show the tooltip, leading to flickering. I've only tested this with GTK tooltips so far. There's also a side issue that subsequent mouse-movement events appear to only be generated after moving a character rather than by a configurable amount of pixels, which leads to the tooltip movement being a bit jerky. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-15 22:03 ` mouse-drag-and-drop-region Alex @ 2017-11-16 15:54 ` Eli Zaretskii 2017-11-17 6:33 ` mouse-drag-and-drop-region Alex 0 siblings, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-16 15:54 UTC (permalink / raw) To: Alex; +Cc: rudalics, tak.kunihiro, emacs-devel > From: Alex <agrambot@gmail.com> > Cc: rudalics@gmx.at, tak.kunihiro@gmail.com, emacs-devel@gnu.org > Date: Wed, 15 Nov 2017 16:03:17 -0600 > > >> I suppose (display-graphic-p) should be supplied as the 2nd argument to > >> `tooltip-show', then? > > > > display-multi-frame-p is more appropriate. > > That appears to be an alias to `display-graphic-p'. That's an implementation detail. But even if it will always remain the alias, using it still conveys the intent more clearly that display-graphic-p, don't you agree? > > But I think the tooltip should not be shown at all on TTY frames, it > > looks unnecessary and even silly to show the dragged text in the echo > > area. > > That sounds better. Though I wonder if tooltips could be shown in TTY > frames using a method similar to how `x-popup-menu' displays a menu in > them? No, it can't. TTY menus pre-empt the command loop, so they cannot be shown during mouse-tracking, AFAIR. > >> I also noticed that when dragging in an X window, the tooltip flickers > >> quite a bit. Is there any easy remedy for this? > > > > We constantly redisplay the tooltip frame, don't we? Or does this > > happen only with GTK tooltips? > > I don't know the details, but it appears that there are some redisplay > cycles that don't show the tooltip, leading to flickering. > > I've only tested this with GTK tooltips so far. Does the flickering disappear if you set x-gtk-use-system-tooltips to nil? > There's also a side issue that subsequent mouse-movement events appear > to only be generated after moving a character rather than by a > configurable amount of pixels, which leads to the tooltip movement being > a bit jerky. If that, too, disappears when GTK tooltips are not used, then maybe it's due to the way we show GTK tooltips. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-16 15:54 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-17 6:33 ` Alex 2017-11-17 7:33 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-17 8:53 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 2 replies; 89+ messages in thread From: Alex @ 2017-11-17 6:33 UTC (permalink / raw) To: Eli Zaretskii; +Cc: rudalics, tak.kunihiro, emacs-devel Eli Zaretskii <eliz@gnu.org> writes: >> > display-multi-frame-p is more appropriate. >> >> That appears to be an alias to `display-graphic-p'. > > That's an implementation detail. But even if it will always remain > the alias, using it still conveys the intent more clearly that > display-graphic-p, don't you agree? Yeah, I agree. >> > But I think the tooltip should not be shown at all on TTY frames, it >> > looks unnecessary and even silly to show the dragged text in the echo >> > area. >> >> That sounds better. Though I wonder if tooltips could be shown in TTY >> frames using a method similar to how `x-popup-menu' displays a menu in >> them? > > No, it can't. TTY menus pre-empt the command loop, so they cannot be > shown during mouse-tracking, AFAIR. I didn't mean to use menus directly, but to use a similar method of displaying something "on top of" a TTY frame. Is displaying the rectangle that makes up a menu necessarily incompatible with a regular command loop? If so, do you know why? >> > We constantly redisplay the tooltip frame, don't we? Or does this >> > happen only with GTK tooltips? >> >> I don't know the details, but it appears that there are some redisplay >> cycles that don't show the tooltip, leading to flickering. >> >> I've only tested this with GTK tooltips so far. > > Does the flickering disappear if you set x-gtk-use-system-tooltips to > nil? Yes, it appears that only GTK tooltips are affected here. Should I file a bug report? >> There's also a side issue that subsequent mouse-movement events appear >> to only be generated after moving a character rather than by a >> configurable amount of pixels, which leads to the tooltip movement being >> a bit jerky. > > If that, too, disappears when GTK tooltips are not used, then maybe > it's due to the way we show GTK tooltips. I don't believe this one has to do with GTK. If you set `track-mouse' to t, then, after the first pixel movement, you will only see mouse-movement events when you move the mouse to a whole character position. This might be intentional, but I think it's poor behaviour. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-17 6:33 ` mouse-drag-and-drop-region Alex @ 2017-11-17 7:33 ` Eli Zaretskii 2017-11-17 15:58 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-18 6:48 ` mouse-drag-and-drop-region Alex 2017-11-17 8:53 ` mouse-drag-and-drop-region martin rudalics 1 sibling, 2 replies; 89+ messages in thread From: Eli Zaretskii @ 2017-11-17 7:33 UTC (permalink / raw) To: Alex; +Cc: rudalics, tak.kunihiro, emacs-devel > From: Alex <agrambot@gmail.com> > Cc: rudalics@gmx.at, tak.kunihiro@gmail.com, emacs-devel@gnu.org > Date: Fri, 17 Nov 2017 00:33:48 -0600 > > >> That sounds better. Though I wonder if tooltips could be shown in TTY > >> frames using a method similar to how `x-popup-menu' displays a menu in > >> them? > > > > No, it can't. TTY menus pre-empt the command loop, so they cannot be > > shown during mouse-tracking, AFAIR. > > I didn't mean to use menus directly, but to use a similar method of > displaying something "on top of" a TTY frame. Is displaying the > rectangle that makes up a menu necessarily incompatible with a regular > command loop? Yes, it is incompatible. > If so, do you know why? Because TTY menus are implemented by overwriting parts of the glyph matrix with text that comes "out of nowhere", as far as the normal redisplay is concerned. IOW, there's no buffer or display string or overlay string that the display engine knows about that produce this text. So if we let the command loop do its thing, it will eventually enter redisplay, and the menu will be erased, partially or fully. > > Does the flickering disappear if you set x-gtk-use-system-tooltips to > > nil? > > Yes, it appears that only GTK tooltips are affected here. Should I file > a bug report? Yes, of course. Though I doubt we have the expertise to fix it (or maybe it's even unfixable as long as we implement the GTK support the way we do). > >> There's also a side issue that subsequent mouse-movement events appear > >> to only be generated after moving a character rather than by a > >> configurable amount of pixels, which leads to the tooltip movement being > >> a bit jerky. > > > > If that, too, disappears when GTK tooltips are not used, then maybe > > it's due to the way we show GTK tooltips. > > I don't believe this one has to do with GTK. If you set `track-mouse' to > t, then, after the first pixel movement, you will only see > mouse-movement events when you move the mouse to a whole character > position. This might be intentional, but I think it's poor behaviour. Can you show a Lisp recipe to reproduce this? ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-17 7:33 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-17 15:58 ` Stefan Monnier 2017-11-17 16:39 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-18 6:48 ` mouse-drag-and-drop-region Alex 1 sibling, 1 reply; 89+ messages in thread From: Stefan Monnier @ 2017-11-17 15:58 UTC (permalink / raw) To: emacs-devel >> >> That sounds better. Though I wonder if tooltips could be shown in TTY >> >> frames using a method similar to how `x-popup-menu' displays a menu in >> >> them? [...] > Because TTY menus are implemented by overwriting parts of the glyph > matrix with text that comes "out of nowhere", as far as the normal > redisplay is concerned. If we really wanted, we could implement some kind of tooltips in a similar way, tho: - overwrite parts of the glyph matrix - register some "pre-redisplay hook" - return to the normal command loop the "pre-redisplay hook" would then remove the tooltip-overwrite from the glyph matrix before the redisplay bumps into it. Then if we want the tooltip to last longer than "until the next redisplay" (which sounds rather likely), we'd need some way to re-add the tooltip after the redisplay is done. Sounds pretty ugly/messy, obviously. A more general solution could be to add two more glyph matrices (one for overlay thingies like menus and tooltips, and another that combines the "normal" glyph matrix with the one for overlay thingies (and it's this one which is then sent to be displayed)). Stefan ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-17 15:58 ` mouse-drag-and-drop-region Stefan Monnier @ 2017-11-17 16:39 ` Eli Zaretskii 2017-11-17 22:44 ` mouse-drag-and-drop-region Stefan Monnier 0 siblings, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-17 16:39 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Date: Fri, 17 Nov 2017 10:58:57 -0500 > > > Because TTY menus are implemented by overwriting parts of the glyph > > matrix with text that comes "out of nowhere", as far as the normal > > redisplay is concerned. > > If we really wanted, we could implement some kind of tooltips in > a similar way, tho: > > - overwrite parts of the glyph matrix > - register some "pre-redisplay hook" > - return to the normal command loop > > the "pre-redisplay hook" would then remove the tooltip-overwrite from the > glyph matrix before the redisplay bumps into it. Then if we want the > tooltip to last longer than "until the next redisplay" (which sounds > rather likely), we'd need some way to re-add the tooltip after the > redisplay is done. > > Sounds pretty ugly/messy, obviously. Not only that, it probably won't work without much more ugliness to support it. > A more general solution could be to add two more glyph matrices (one for > overlay thingies like menus and tooltips, and another that combines the > "normal" glyph matrix with the one for overlay thingies (and it's this > one which is then sent to be displayed)). I don't see how this solves the problem, because the display engine will still know nothing about that "second" matrix. The only way to make TTY menus a first-class display citizen is to come up with some object which the display engine would routinely consult in deciding what to display in a window. Right now, it consults the text of the buffer pointed to by the window, and any Lisp strings related to the buffer. We need something else to add to this soup, and the problem with that something is that it spans several lines, but only part of each line. Maybe it should be modeled on the mouse-highlight, with the assumption of a rectangular region added... ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-17 16:39 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-17 22:44 ` Stefan Monnier 2017-11-18 7:54 ` mouse-drag-and-drop-region Eli Zaretskii 0 siblings, 1 reply; 89+ messages in thread From: Stefan Monnier @ 2017-11-17 22:44 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel >> A more general solution could be to add two more glyph matrices (one for >> overlay thingies like menus and tooltips, and another that combines the >> "normal" glyph matrix with the one for overlay thingies (and it's this >> one which is then sent to be displayed)). > I don't see how this solves the problem, because the display engine > will still know nothing about that "second" matrix. As mentioned: "it's this one which is then sent to be displayed", so this assumes we'd change the display engine to use the combined matrix: render buffer text to desired-glyph-matrix combine desired-glyph-matrix with overlay-matrix into combined-matrix send combined-matrix to screen -- Stefan ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-17 22:44 ` mouse-drag-and-drop-region Stefan Monnier @ 2017-11-18 7:54 ` Eli Zaretskii 2017-11-18 14:36 ` mouse-drag-and-drop-region Stefan Monnier 0 siblings, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-18 7:54 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: emacs-devel@gnu.org > Date: Fri, 17 Nov 2017 17:44:02 -0500 > > > I don't see how this solves the problem, because the display engine > > will still know nothing about that "second" matrix. > > As mentioned: "it's this one which is then sent to be displayed", so > this assumes we'd change the display engine to use the combined matrix: > > render buffer text to desired-glyph-matrix > combine desired-glyph-matrix with overlay-matrix into combined-matrix > send combined-matrix to screen If you mean that literally, then the above will disable (almost) all redisplay optimizations, and will cause Emacs always to display each window in its entirety. Redisplay optimizations require that Emacs be able to _reason_ about parts of the window display being unchanged, by looking at the related objects and variables -- buffers, overlays, etc. You introduce a factor into this equation about which Emacs will not be able to reason, because its relation to the other objects is unknown. E.g., the most frequent redisplay use case is cursor movement with no other changes. This case is detected and handled specially, because it must be fast. How will that work with your proposal, when cursor motion will (or could) change some parts in that "second" matrix? Am I missing something? ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-18 7:54 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-18 14:36 ` Stefan Monnier 2017-11-18 15:04 ` mouse-drag-and-drop-region Eli Zaretskii 0 siblings, 1 reply; 89+ messages in thread From: Stefan Monnier @ 2017-11-18 14:36 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel >> render buffer text to desired-glyph-matrix >> combine desired-glyph-matrix with overlay-matrix into combined-matrix >> send combined-matrix to screen > If you mean that literally, then the above will disable (almost) all > redisplay optimizations, and will cause Emacs always to display each > window in its entirety. > Redisplay optimizations require that Emacs be > able to _reason_ about parts of the window display being unchanged, by > looking at the related objects and variables -- buffers, overlays, > etc. The above is the *model*. I'd describe the current model as: render buffer text to glyph-matrix send glyph-matrix to screen both models are amenable to various optimizations. Most of the optimizations applicable to the current model should be applicable to the other as well. Stefan ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-18 14:36 ` mouse-drag-and-drop-region Stefan Monnier @ 2017-11-18 15:04 ` Eli Zaretskii 2017-11-18 15:49 ` mouse-drag-and-drop-region Stefan Monnier 0 siblings, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-18 15:04 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: emacs-devel@gnu.org > Date: Sat, 18 Nov 2017 09:36:40 -0500 > > > Redisplay optimizations require that Emacs be > > able to _reason_ about parts of the window display being unchanged, by > > looking at the related objects and variables -- buffers, overlays, > > etc. > > The above is the *model*. I'd describe the current model as: > > render buffer text to glyph-matrix > send glyph-matrix to screen This model is incomplete. Emacs first tries to reuse (parts of) the current matrix, if that's possible given the information about what has changed since the last redisplay cycle. It only generates a new ("desired") glyph matrix if the attempt to reuse the current one failed. In addition, AFAIR there are situations when only small portions of the desired matrix are generated. When doing this, Emacs must be able to decide which parts don't need to be regenerated. > both models are amenable to various optimizations. Most of the > optimizations applicable to the current model should be applicable to > the other as well. If you are thinking about reviewing the existing optimizations and changing them to account for the new model, including adding some new optimization methods, then I'm sure it's possible. But it's a large job, and I cannot promise that the result will be acceptable, performance-wise, unless very deep changes are done in the control and logic flow of the current code. IOW, I think the way redisplay is implemented simply isn't ready for such changes. The current implementation of the TTY menus was proposed by Gerd Möllmann, the author of the current display engine; if something like what you suggest were feasible, he'd most probably mention it when this was discussed. He didn't. Of course, it's possible that he simply didn't think about such an alternative, but I personally find that unlikely. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-18 15:04 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-18 15:49 ` Stefan Monnier 0 siblings, 0 replies; 89+ messages in thread From: Stefan Monnier @ 2017-11-18 15:49 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel > This model is incomplete. Emacs first tries to reuse (parts of) the > current matrix, if that's possible given the information about what > has changed since the last redisplay cycle. It only generates a new > ("desired") glyph matrix if the attempt to reuse the current one > failed. > In addition, AFAIR there are situations when only small portions of > the desired matrix are generated. When doing this, Emacs must be able > to decide which parts don't need to be regenerated. Right. These are optimizations which would apply identically to the other model, (where the "current matrix" would be the "desired matrix" computed last time, rather than the "combined matrix" computed last time). > If you are thinking about reviewing the existing optimizations and > changing them to account for the new model, including adding some new > optimization methods, then I'm sure it's possible. But it's a large > job, and I cannot promise that the result will be acceptable, > performance-wise, unless very deep changes are done in the control and > logic flow of the current code. Indeed. I'm pretty sure it can be done with good enough performance, but I do not know how much work it would take. Stefan ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-17 7:33 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-17 15:58 ` mouse-drag-and-drop-region Stefan Monnier @ 2017-11-18 6:48 ` Alex 2017-11-18 9:07 ` mouse-drag-and-drop-region Eli Zaretskii 1 sibling, 1 reply; 89+ messages in thread From: Alex @ 2017-11-18 6:48 UTC (permalink / raw) To: Eli Zaretskii; +Cc: rudalics, tak.kunihiro, emacs-devel Eli Zaretskii <eliz@gnu.org> writes: >> If so, do you know why? > > Because TTY menus are implemented by overwriting parts of the glyph > matrix with text that comes "out of nowhere", as far as the normal > redisplay is concerned. IOW, there's no buffer or display string or > overlay string that the display engine knows about that produce this > text. So if we let the command loop do its thing, it will eventually > enter redisplay, and the menu will be erased, partially or fully. Oh, that's unfortunate. Thanks for the explanation. >> > If that, too, disappears when GTK tooltips are not used, then maybe >> > it's due to the way we show GTK tooltips. >> >> I don't believe this one has to do with GTK. If you set `track-mouse' to >> t, then, after the first pixel movement, you will only see >> mouse-movement events when you move the mouse to a whole character >> position. This might be intentional, but I think it's poor behaviour. > > Can you show a Lisp recipe to reproduce this? (setq track-mouse t) (setq count 0) (global-set-key [mouse-movement] (lambda () (interactive) (message "%d" (setq count (1+ count))))) This will only message on the first mouse-movement event (after a non-mouse-movement event), and after moving to a new character position. It also messages after a down-click, which feels like a bug. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-18 6:48 ` mouse-drag-and-drop-region Alex @ 2017-11-18 9:07 ` Eli Zaretskii 2017-11-18 21:58 ` mouse-drag-and-drop-region Alex 0 siblings, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-18 9:07 UTC (permalink / raw) To: Alex; +Cc: rudalics, tak.kunihiro, emacs-devel > From: Alex <agrambot@gmail.com> > Date: Sat, 18 Nov 2017 00:48:27 -0600 > Cc: rudalics@gmx.at, tak.kunihiro@gmail.com, emacs-devel@gnu.org > > Eli Zaretskii <eliz@gnu.org> writes: > >> If so, do you know why? > > > > Because TTY menus are implemented by overwriting parts of the glyph > > matrix with text that comes "out of nowhere", as far as the normal > > redisplay is concerned. IOW, there's no buffer or display string or > > overlay string that the display engine knows about that produce this > > text. So if we let the command loop do its thing, it will eventually > > enter redisplay, and the menu will be erased, partially or fully. > > Oh, that's unfortunate. If you or someone else has better ideas for implementing menus on a TTY, let's hear them. > >> I don't believe this one has to do with GTK. If you set `track-mouse' to > >> t, then, after the first pixel movement, you will only see > >> mouse-movement events when you move the mouse to a whole character > >> position. This might be intentional, but I think it's poor behaviour. > > > > Can you show a Lisp recipe to reproduce this? > > (setq track-mouse t) > (setq count 0) > > (global-set-key [mouse-movement] > (lambda () > (interactive) > (message "%d" (setq count (1+ count))))) > > This will only message on the first mouse-movement event (after a > non-mouse-movement event), and after moving to a new character position. That's the intended behavior, see note_mouse_movement. > It also messages after a down-click, which feels like a bug. Not here, it doesn't. I only see a message after a movement to another glyph. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-18 9:07 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-18 21:58 ` Alex 2017-11-19 15:27 ` mouse-drag-and-drop-region Eli Zaretskii 0 siblings, 1 reply; 89+ messages in thread From: Alex @ 2017-11-18 21:58 UTC (permalink / raw) To: Eli Zaretskii; +Cc: rudalics, emacs-devel Eli Zaretskii <eliz@gnu.org> writes: >> > Can you show a Lisp recipe to reproduce this? >> >> (setq track-mouse t) >> (setq count 0) >> >> (global-set-key [mouse-movement] >> (lambda () >> (interactive) >> (message "%d" (setq count (1+ count))))) >> >> This will only message on the first mouse-movement event (after a >> non-mouse-movement event), and after moving to a new character position. > > That's the intended behavior, see note_mouse_movement. Thanks for pointing me to it. I can understand the intention, but I think it would be useful to be able to track the mouse with every pixel change in addition to the current behaviour. On topic, it should make dragging the tooltip a lot smoother. Would such a feature be considered? I'm not sure what the best way to implement it would be; perhaps a new value for track-mouse? Then note_mouse_movement could conditionally use last_mouse_motion_{x,y}? >> It also messages after a down-click, which feels like a bug. > > Not here, it doesn't. I only see a message after a movement to > another glyph. That's odd, you can't reproduce it at all? On my end, I sometimes have to click a few times (sometimes slowly) before an erroneous message appears. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-18 21:58 ` mouse-drag-and-drop-region Alex @ 2017-11-19 15:27 ` Eli Zaretskii 0 siblings, 0 replies; 89+ messages in thread From: Eli Zaretskii @ 2017-11-19 15:27 UTC (permalink / raw) To: Alex; +Cc: rudalics, emacs-devel > From: Alex <agrambot@gmail.com> > Cc: rudalics@gmx.at, emacs-devel@gnu.org > Date: Sat, 18 Nov 2017 15:58:17 -0600 > > >> This will only message on the first mouse-movement event (after a > >> non-mouse-movement event), and after moving to a new character position. > > > > That's the intended behavior, see note_mouse_movement. > > Thanks for pointing me to it. I can understand the intention, but I > think it would be useful to be able to track the mouse with every pixel > change in addition to the current behaviour. On topic, it should make > dragging the tooltip a lot smoother. Does it, indeed? Did you try that? > Would such a feature be considered? What other uses would it have except this one (assuming it helps there)? It will certainly flood Emacs with input events, the question is: is that justified? > >> It also messages after a down-click, which feels like a bug. > > > > Not here, it doesn't. I only see a message after a movement to > > another glyph. > > That's odd, you can't reproduce it at all? No. > On my end, I sometimes have to click a few times (sometimes slowly) > before an erroneous message appears. GTK issue again, perhaps? ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-17 6:33 ` mouse-drag-and-drop-region Alex 2017-11-17 7:33 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-17 8:53 ` martin rudalics 2017-11-18 6:49 ` mouse-drag-and-drop-region Alex 1 sibling, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-11-17 8:53 UTC (permalink / raw) To: Alex, Eli Zaretskii; +Cc: tak.kunihiro, emacs-devel > I don't believe this one has to do with GTK. If you set `track-mouse' to > t, then, after the first pixel movement, you will only see > mouse-movement events when you move the mouse to a whole character > position. This might be intentional, but I think it's poor behaviour. Does anything change when setting 'frame-resize-pixelwise' to t? martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-17 8:53 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-18 6:49 ` Alex 0 siblings, 0 replies; 89+ messages in thread From: Alex @ 2017-11-18 6:49 UTC (permalink / raw) To: martin rudalics; +Cc: Eli Zaretskii, emacs-devel martin rudalics <rudalics@gmx.at> writes: >> I don't believe this one has to do with GTK. If you set `track-mouse' to >> t, then, after the first pixel movement, you will only see >> mouse-movement events when you move the mouse to a whole character >> position. This might be intentional, but I think it's poor behaviour. > > Does anything change when setting 'frame-resize-pixelwise' to t? > > martin No, unfortunately. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-15 19:46 ` mouse-drag-and-drop-region Alex 2017-11-15 20:15 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-16 9:04 ` martin rudalics 2017-11-17 6:02 ` mouse-drag-and-drop-region Alex 1 sibling, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-11-16 9:04 UTC (permalink / raw) To: Alex; +Cc: Eli Zaretskii, tak.kunihiro, emacs-devel > 1. Select a region. > 2. Hold down-mouse-1 inside of this region. > 3. Press any key before moving or releasing the mouse. > > Doing this yields an error without your change, Something like mouse-drag-region: Wrong type argument: char-or-string-p, nil I suppose. 'value-selection' must have been nil then. > and it pastes the region > with your change. Even when this key is C-g, `mark-active' is t after > step 3. Not much better. But doing mouse-down and pressing another key at the same time is somewhat obscure behavior. > I suppose (display-graphic-p) should be supplied as the 2nd argument to > `tooltip-show', then? For example, yes. > I also noticed that when dragging in an X window, the tooltip flickers > quite a bit. Is there any easy remedy for this? Removing the > `mouse-set-point' call in `track-mouse' helps in some cases, but not > completely. Would customizing 'tooltip-reuse-hidden-frame' change anything or are you using GTK tooltips? martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-16 9:04 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-17 6:02 ` Alex 2017-11-17 8:53 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Alex @ 2017-11-17 6:02 UTC (permalink / raw) To: martin rudalics; +Cc: Eli Zaretskii, tak.kunihiro, emacs-devel martin rudalics <rudalics@gmx.at> writes: >> 1. Select a region. >> 2. Hold down-mouse-1 inside of this region. >> 3. Press any key before moving or releasing the mouse. >> >> Doing this yields an error without your change, > > Something like > > mouse-drag-region: Wrong type argument: char-or-string-p, nil > > I suppose. 'value-selection' must have been nil then. Right, that's the issue. Or perhaps _an_ issue, since `kill-region' is sent nil arguments in this case. >> and it pastes the region >> with your change. Even when this key is C-g, `mark-active' is t after >> step 3. > > Not much better. But doing mouse-down and pressing another key at the > same time is somewhat obscure behavior. Somewhat obscure, but it should be handled better, right? >> I also noticed that when dragging in an X window, the tooltip flickers >> quite a bit. Is there any easy remedy for this? Removing the >> `mouse-set-point' call in `track-mouse' helps in some cases, but not >> completely. > > Would customizing 'tooltip-reuse-hidden-frame' change anything or are > you using GTK tooltips? It appears that it only happens with GTK tooltips. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-17 6:02 ` mouse-drag-and-drop-region Alex @ 2017-11-17 8:53 ` martin rudalics 0 siblings, 0 replies; 89+ messages in thread From: martin rudalics @ 2017-11-17 8:53 UTC (permalink / raw) To: Alex; +Cc: Eli Zaretskii, tak.kunihiro, emacs-devel >> Not much better. But doing mouse-down and pressing another key at the >> same time is somewhat obscure behavior. > > Somewhat obscure, but it should be handled better, right? Right. > It appears that it only happens with GTK tooltips. GTK tooltips are a pain. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-14 20:17 ` mouse-drag-and-drop-region Alex 2017-11-15 9:22 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-15 20:22 ` Eli Zaretskii 1 sibling, 0 replies; 89+ messages in thread From: Eli Zaretskii @ 2017-11-15 20:22 UTC (permalink / raw) To: Alex; +Cc: rudalics, tak.kunihiro, emacs-devel > From: Alex <agrambot@gmail.com> > Cc: emacs-devel <emacs-devel@gnu.org>, tak.kunihiro@gmail.com, Eli Zaretskii <eliz@gnu.org> > Date: Tue, 14 Nov 2017 14:17:25 -0600 > > Eli, would it be okay to make the same `read-event' -> `read-key' change > (specific to xt-mouse as in Bug#29150) here as well to tide over until > the function uses `set-transient-map'? This is a new feature, so we can do that unconditionally. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-14 9:54 mouse-drag-and-drop-region martin rudalics 2017-11-14 17:01 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-14 20:17 ` mouse-drag-and-drop-region Alex @ 2017-11-16 0:28 ` Tak Kunihiro 2017-11-16 9:11 ` mouse-drag-and-drop-region martin rudalics 2 siblings, 1 reply; 89+ messages in thread From: Tak Kunihiro @ 2017-11-16 0:28 UTC (permalink / raw) To: rudalics; +Cc: tak.kunihiro, emacs-devel > (1) Why does the value selection happen within the ‘track-mouse’ > form and why do you delete the mouse overlay? That is, why > don't we move this part > > (unless value-selection ; initialization > (delete-overlay mouse-secondary-overlay) > (setq value-selection (buffer-substring > start end)) > (move-overlay mouse-secondary-overlay > start end)) ; (deactivate-mark) > > right to the beginning so we have something like > > (let* ((start (region-beginning)) > (end (region-end)) > (point (point)) > (buffer (current-buffer)) > (window (selected-window)) > (value-selection (buffer-substring start > end))) > (move-overlay mouse-secondary-overlay start > end) > (track-mouse > ... > > there? There could be two operations that are `click' and `drag'. Later on line 40, value-selection is also used to identify whether operation is `drag'. Probably code should be improved. 39: ;; "drag negligible" or "drag to read-only", restore region. 40: (value-selection 41: (select-window window) ; In case miss drag to other window 42: (goto-char point) > (2) Activating the secondary overlay can be distracting and should > be made optional (facultatively keeping the primary overlay in > place provided (4) below is done). Region on the other window is not visible. Thus original region should be hi-lighted somehow. Since mouse-drag-and-drop-region is located on mouse.el, mouse-secondary-overlay was used. Do you suggest to have option such like (defvar mouse-drag-and-drop-region-overlay 'mouse-secondary-overlay) ? > (3) Showing tooltips can be distracting and should be optional. > Note also, that usurping tooltips this way may prevent them from > showing interesting properties of the drop area like whether the > text there is read only. OTOH we might consider retaining > properties of the text in (non-GTK) tooltips. Do you suggest to have option like (defvar mouse-drag-and-drop-region-preview t) or implement other way to show the text besides using tooltips? > (4) The (deactivate-mark) and (mouse-set-point event) trick to allow > showing point the way ‘mouse-drag-track’ does can be distracting > and should be made optional. I think that this is very related to 2, 3, and 5 (as you inferred). > (5) The mouse pointer shape should take care of indicating the exact > position where the drop occurs. We should probably also signal > whenever the current drop position is invalid. This is IIUC > usual practice on most window systems now. I think it is a good idea. > (6) Dropping should allow to copy text into the region itself. > There's no reason forbidding that. I suppose that you mean when drop onto region itself with key pressed. I agree. > (7) IMO either cutting should be the default too when the drop > occurs in a different buffer or copying would be the default and > pressing the modifier should produce a cut instead. The current > behavior wants me to always keep in mind whether the target > buffer is the same as the source buffer. At least, this > behavior should be made optional. Default behavior followed that of file browser on `drag' a file. Between the same volume (buffer), `drag' does `cut' instead of `copy'. I prefer current behavior as default but have no objection to have option something like (defvar mouse-drag-and-drop-region-cut-hungry t) . > (8) Read-only text should be handled. An attempt to drop text into > a read-only area should be signalled to the user. An attempt to > cut text from a read-only text/buffer should be signalled as > well. > For the latter, we copy text instead (cf C-w in read-only text). So > I think this feature should behave similarly, at least by default. > I just noticed that the code does use ‘kill-region’ already. This > has the side-effect of putting the text into the kill ring, > something which should be documented at least. But I think the code > should rather use ‘delete-region’ instead with the behavior you > proposed. I suppose that you suggest to tell user more explicitly in echo area how he cannot change the text. I am not against the suggestion. On an user perspective, operation `drag-and-drop-region' is a combination of `cut' and `paste'. Thus text was killed instead of deleted. How you think delete is more preferred? I have no objection to document it. > (9) The code must become resilient against any failures by wrapping > it into a ‘condition-case’ and doing the necessary clean up > operations (restoring region and point, deleting the secondary > overlay). > > I think (8) and (9) should be fixed before the release. As for > future releases we might also consider a ‘set-transient-map’ based > solution. No objection. There is other thread about mouse-drag-and-drop-region. https://lists.gnu.org/archive/html/emacs-devel/2017-10/msg00588.html ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-16 0:28 ` mouse-drag-and-drop-region Tak Kunihiro @ 2017-11-16 9:11 ` martin rudalics 2017-11-20 13:29 ` mouse-drag-and-drop-region Tak Kunihiro 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-11-16 9:11 UTC (permalink / raw) To: Tak Kunihiro; +Cc: emacs-devel > There could be two operations that are `click' and `drag'. Later on > line 40, value-selection is also used to identify whether operation is > `drag'. Probably code should be improved. Did you ever consider using the "r" interactive switch instead of the "e" one? >> (2) Activating the secondary overlay can be distracting and should >> be made optional (facultatively keeping the primary overlay in >> place provided (4) below is done). > > Region on the other window is not visible. Thus original region > should be hi-lighted somehow. Since mouse-drag-and-drop-region is > located on mouse.el, mouse-secondary-overlay was used. You mean that you highlight the original region with the secondary overlay so that the overlay shows up on the target window as well and the user is informed that dropping there might lead to say "dubious" results? > Do you suggest to have option such like > (defvar mouse-drag-and-drop-region-overlay 'mouse-secondary-overlay) > ? I mean something like (defcustom mouse-drag-and-drop-region-show-secondary-overlay t ...) where setting this to nil means to just not show any overlay. And your code would have to accept that there is no secondary overlay at the time of the drop. >> (3) Showing tooltips can be distracting and should be optional. >> Note also, that usurping tooltips this way may prevent them from >> showing interesting properties of the drop area like whether the >> text there is read only. OTOH we might consider retaining >> properties of the text in (non-GTK) tooltips. > > Do you suggest to have option like > (defvar mouse-drag-and-drop-region-preview t) > or implement other way to show the text besides using tooltips? I would say (defcustom mouse-drag-and-drop-region-show-tooltip t) and never show a tooltip on text-only terminals even if this is t. >> (4) The (deactivate-mark) and (mouse-set-point event) trick to allow >> showing point the way ‘mouse-drag-track’ does can be distracting >> and should be made optional. > > I think that this is very related to 2, 3, and 5 (as you inferred). Yes. It's irritating to drag a block cursor with the mouse. Do you know of any other applications which do such a thing? >> (5) The mouse pointer shape should take care of indicating the exact >> position where the drop occurs. We should probably also signal >> whenever the current drop position is invalid. This is IIUC >> usual practice on most window systems now. > > I think it is a good idea. We probably need to define additional cursors for this so it's not for Emacs 26. >> (7) IMO either cutting should be the default too when the drop >> occurs in a different buffer or copying would be the default and >> pressing the modifier should produce a cut instead. The current >> behavior wants me to always keep in mind whether the target >> buffer is the same as the source buffer. At least, this >> behavior should be made optional. > > Default behavior followed that of file browser on `drag' a file. Which file browser? > Between the same volume (buffer), `drag' does `cut' instead of `copy'. > I prefer current behavior as default but have > no objection to have option something like > (defvar mouse-drag-and-drop-region-cut-hungry t) I would be more radical with (defcustom mouse-drag-and-drop-region-cut-or-copy t) where the values 'cut and 'copy would always categorically cut or copy (unless the value of 'mouse-drag-and-drop-region' implies to copy instead of cut) and t means your original behavior. >> (8) Read-only text should be handled. An attempt to drop text into >> a read-only area should be signalled to the user. An attempt to >> cut text from a read-only text/buffer should be signalled as >> well. > >> For the latter, we copy text instead (cf C-w in read-only text). So >> I think this feature should behave similarly, at least by default. > >> I just noticed that the code does use ‘kill-region’ already. This >> has the side-effect of putting the text into the kill ring, >> something which should be documented at least. But I think the code >> should rather use ‘delete-region’ instead with the behavior you >> proposed. > > I suppose that you suggest to tell user more explicitly in echo area > how he cannot change the text. The echo area should be avoided during tracking. Think of users who invoke 'mouse-drag-and-drop-region' on a frame without a minibuffer. I think that first of all you should use 'delete-region' instead of 'kill-region' to avoid the above-mentioned side effect. Then your code should silently swallow any bugs for cutting from read-only text provided 'kill-read-only-ok' is t. For that purpose, simply peruse the corresponding code from 'kill-region'. A final drop into read-only text should always give an error. We should be able to redeem that by providing a feedback in form of a mouse cursor when the mouse is either over read-only text or no buffer text at all. > On an user perspective, operation `drag-and-drop-region' is a > combination of `cut' and `paste'. Thus text was killed instead of > deleted. How you think delete is more preferred? I have no objection > to document it. IMO using 'kill-region' is an unexpected side effect. If people think differently, we could add yet another option like (defucstom mouse-drag-and-drop-region-cut-does-kill-region t) > There is other thread about mouse-drag-and-drop-region. > > https://lists.gnu.org/archive/html/emacs-devel/2017-10/msg00588.html I'm aware of that. I have changed some Emacs internals to make it work here but I have no idea of the consequences these changes might have for other mouse-tracking functions. So this is strictly for Emacs 27. Thanks, martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-16 9:11 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-20 13:29 ` Tak Kunihiro 2017-11-20 16:03 ` mouse-drag-and-drop-region Drew Adams 2017-11-21 9:24 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 2 replies; 89+ messages in thread From: Tak Kunihiro @ 2017-11-20 13:29 UTC (permalink / raw) To: rudalics, Eli Zaretskii, Alex; +Cc: tak.kunihiro, emacs-devel I revised mouse-drag-and-drop-region. I'm sending replay to https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00387.html, ChangeLog, and patch. * ChangeLog 2017-11-21 Tak Kunihiro <tkk@misasa.okayama-u.ac.jp> Improve comments and have two new options * lisp/mouse.el (mouse-drag-and-drop-region): Make tooltip preview to be an option. Have an option to make dragging cut among buffers. (mouse-drag-and-drop-region-cut-among-buffer): New flag. When t, text is cut instead of copy when dragged among buffers. (mouse-drag-and-drop-region-show-tooltip): New flag. When t, text is shown by a tooltip in a graphic display. * Replay > Did you ever consider using the "r" interactive switch instead of the > "e" one? I suppose you suggest something like below. I cannot make this work. Thus this revision, I do not use "r" interactive switch. (defun mouse-drag-and-drop-region (event start and) (interactive "e\nr") ...) >>> (2) Activating the secondary overlay can be distracting and should >>> be made optional (facultatively keeping the primary overlay in >>> place provided (4) below is done). >> >> Region on the other window is not visible. Thus original region >> should be hi-lighted somehow. Since mouse-drag-and-drop-region is >> located on mouse.el, mouse-secondary-overlay was used. > > You mean that you highlight the original region with the secondary > overlay so that the overlay shows up on the target window as well and > the user is informed that dropping there might lead to say "dubious" > results? I think yes. Also, since value-selection would be inserted before the point and mark, I thought it is handy to keep track where was the region by an overlay. > I mean something like > > (defcustom mouse-drag-and-drop-region-show-secondary-overlay t ...) > > where setting this to nil means to just not show any overlay. And > your code would have to accept that there is no secondary overlay at > the time of the drop. I found this takes significant time. I skip to get rid of usage of secondary-overlay on this revision. >>> (3) Showing tooltips can be distracting and should be optional. >>> Note also, that usurping tooltips this way may prevent them from >>> showing interesting properties of the drop area like whether the >>> text there is read only. OTOH we might consider retaining >>> properties of the text in (non-GTK) tooltips. >> > I would say > > (defcustom mouse-drag-and-drop-region-show-tooltip t) > > and never show a tooltip on text-only terminals even if this is t. OK. >>> (4) The (deactivate-mark) and (mouse-set-point event) trick to allow >>> showing point the way ‘mouse-drag-track’ does can be distracting >>> and should be made optional. >> >> I think that this is very related to 2, 3, and 5 (as you inferred). > > Yes. It's irritating to drag a block cursor with the mouse. Do you > know of any other applications which do such a thing? I cannot think of a way to show insert point besides (mouse-set-point event). Do you suggest overlay-put "|" or change cursor-type to 'bar during drag? I thought who prefers bar changes the default cursor anyway. I did not revise code in this respect. >>> (5) The mouse pointer shape should take care of indicating the exact >>> position where the drop occurs. We should probably also signal >>> whenever the current drop position is invalid. This is IIUC >>> usual practice on most window systems now. >> >> I think it is a good idea. > > We probably need to define additional cursors for this so it's not for > Emacs 26. I did not revise code in this aspect. >>> (7) IMO either cutting should be the default too when the drop >>> occurs in a different buffer or copying would be the default and >>> pressing the modifier should produce a cut instead. The current >>> behavior wants me to always keep in mind whether the target >>> buffer is the same as the source buffer. At least, this >>> behavior should be made optional. >> >> Default behavior followed that of file browser on `drag' a file. > > Which file browser? Finder on macOS and File Explorer on Windows 10 behave like that way. >> Between the same volume (buffer), `drag' does `cut' instead of `copy'. >> I prefer current behavior as default but have >> no objection to have option something like >> (defvar mouse-drag-and-drop-region-cut-hungry t) > > I would be more radical with > > (defcustom mouse-drag-and-drop-region-cut-or-copy t) > > where the values 'cut and 'copy would always categorically cut or copy > (unless the value of 'mouse-drag-and-drop-region' implies to copy > instead of cut) and t means your original behavior. A new option was created. Now `cut' can be default even among buffers. (defvar mouse-drag-and-drop-region-cut-among-buffer nil "When t, text is cut instead of copy when dragged among buffers.") >>> (8) Read-only text should be handled. An attempt to drop text into >>> a read-only area should be signalled to the user. An attempt to >>> cut text from a read-only text/buffer should be signalled as >>> well. >> >>> For the latter, we copy text instead (cf C-w in read-only text). So >>> I think this feature should behave similarly, at least by default. >> >>> I just noticed that the code does use ‘kill-region’ already. This >>> has the side-effect of putting the text into the kill ring, >>> something which should be documented at least. But I think the code >>> should rather use ‘delete-region’ instead with the behavior you >>> proposed. >> >> I suppose that you suggest to tell user more explicitly in echo area >> how he cannot change the text. > > The echo area should be avoided during tracking. Think of users who > invoke 'mouse-drag-and-drop-region' on a frame without a minibuffer. OK. > I think that first of all you should use 'delete-region' instead of > 'kill-region' to avoid the above-mentioned side effect. Then your > code should silently swallow any bugs for cutting from read-only > text provided 'kill-read-only-ok' is t. For that purpose, simply > peruse the corresponding code from 'kill-region'. OK. Now `delete-region' is used. > A final drop into read-only text should always give an error. We > should be able to redeem that by providing a feedback in form of a > mouse cursor when the mouse is either over read-only text or no > buffer text at all. I revised only to give message. I could not tell how to bring condition-case to code. >> On an user perspective, operation `drag-and-drop-region' is a >> combination of `cut' and `paste'. Thus text was killed instead of >> deleted. How you think delete is more preferred? I have no >> objection to document it. > IMO using 'kill-region' is an unexpected side effect. If people > think differently, we could add yet another option like > > (defucstom mouse-drag-and-drop-region-cut-does-kill-region t) Now `delete-region' is used instead of `kill-region'. * Patch diff --git a/lisp/mouse.el b/lisp/mouse.el old mode 100644 new mode 100755 index 17d1732..08f70d4 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -2361,6 +2361,12 @@ text is copied instead of being cut." :version "26.1" :group 'mouse) +(defvar mouse-drag-and-drop-region-cut-among-buffer nil + "When t, text is cut instead of copy when dragged among buffers.") + +(defvar mouse-drag-and-drop-region-show-tooltip t + "When t, text is shown by a tooltip in a graphic display.") + (defun mouse-drag-and-drop-region (event) "Move text in the region to point where mouse is dragged to. The transportation of text is also referred as `drag and drop'. @@ -2369,64 +2375,98 @@ modifier key was pressed when dropping, and the value of the variable `mouse-drag-and-drop-region' is that modifier, the text is copied instead of being cut." (interactive "e") - (require 'tooltip) - (let ((start (region-beginning)) + (let ((mouse-drag-and-drop-region-show-tooltip + (and mouse-drag-and-drop-region-show-tooltip + (display-multi-frame-p) + (require 'tooltip))) + (start (region-beginning)) (end (region-end)) (point (point)) (buffer (current-buffer)) (window (selected-window)) - value-selection) + no-modifier-on-drop + value-selection) ; This remains nil when event was "click". (track-mouse - ;; When event was click instead of drag, skip loop + ;; When event was "click" instead of "drag", skip loop. (while (progn (setq event (read-event)) (or (mouse-movement-p event) ;; Handle `mouse-autoselect-window'. (eq (car-safe event) 'select-window))) - (unless value-selection ; initialization + ;; Obtain the text in region. When the loop was skipped, + ;; value-selection remains nil. + (unless value-selection (delete-overlay mouse-secondary-overlay) (setq value-selection (buffer-substring start end)) (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) - (ignore-errors (deactivate-mark) ; care existing region in other window - (mouse-set-point event) - (tooltip-show value-selection))) - (tooltip-hide)) - ;; Do not modify buffer under mouse when "event was click", - ;; "drag negligible", or - ;; "drag to read-only". - (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" - (member 'secondary-selection ; "drag negligible" - (mapcar (lambda (xxx) (overlay-get xxx 'face)) - (overlays-at (posn-point (event-end event))))) - buffer-read-only) - ;; Do not modify buffer under mouse. + (ignore-errors + (deactivate-mark) ; Maintain region in other window. + (mouse-set-point event) + (when mouse-drag-and-drop-region-show-tooltip + (tooltip-show value-selection)))) + ;; Check if modifier was pressed on drop. + (setq no-modifier-on-drop + (not (member mouse-drag-and-drop-region (event-modifiers event)))) + (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide))) + ;; Do not modify buffer under mouse when event is "click", "drag + ;; but negligible", or "drag to read-only". Operation "drag but + ;; negligible" is defined as drag-and-drop the text to + ;; secondary-selection without modifier pressed. When pressed, + ;; the text will be inserted to inside of secondary-selection. + (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "click" + (and (member 'secondary-selection ; "drag but negligible" + (mapcar (lambda (xxx) (overlay-get xxx 'face)) + (overlays-at (posn-point (event-end event))))) + no-modifier-on-drop) + buffer-read-only) ; "drag to read-only" (cond - ;; "drag negligible" or "drag to read-only", restore region. + ;; Set back the original text as region on "drag but negligible" + ;; or "drag to read-only". (value-selection - (select-window window) ; In case miss drag to other window + (if buffer-read-only (message "Buffer is read-only")) ; (barf-if-buffer-read-only) + (select-window window) ; Select the source windows back on miss-drag to other window. (goto-char point) (setq deactivate-mark nil) (activate-mark)) - ;; "event was click" + ;; Move point within region on "click". (t (deactivate-mark) (mouse-set-point event))) - ;; Modify buffer under mouse by inserting text. + ;; Intert the text to destination buffer under mouse. (push-mark) (insert value-selection) - (when (not (equal (mark) (point))) ; on success insert + ;; On success, set the text as region on destination buffer. + (when (not (equal (mark) (point))) (setq deactivate-mark nil) - (activate-mark)) ; have region on destination - ;; Take care of initial region on source. - (if (equal (current-buffer) buffer) ; when same buffer - (let (deactivate-mark) ; remove text - (unless (member mouse-drag-and-drop-region (event-modifiers event)) - (kill-region (overlay-start mouse-secondary-overlay) - (overlay-end mouse-secondary-overlay)))) - (let ((window1 (selected-window))) ; when beyond buffer - (select-window window) - (goto-char point) ; restore point on source window - (activate-mark) ; restore region + (activate-mark)) + ;; Set back the original text as region or delete the original + ;; text on source buffer. + (if (equal (current-buffer) buffer) + ;; When source buffer and destination buffer are the same, + ;; remove the original text. + (let (deactivate-mark) + (if no-modifier-on-drop + (delete-region (overlay-start mouse-secondary-overlay) + (overlay-end mouse-secondary-overlay)))) + ;; When source buffer and destination buffer are different, + ;; keep (set back the original text as region) or remove the + ;; original text. + (let ((window1 (selected-window))) + (select-window window) ; Select window with source buffer. + (goto-char point) ; Move point to the original text on source buffer. + (if (or (if no-modifier-on-drop + (not mouse-drag-and-drop-region-cut-among-buffer) + mouse-drag-and-drop-region-cut-among-buffer) + buffer-read-only) + ;; Set back the original text as region on source buffer + ;; like operation `copy'. + (progn + (if buffer-read-only (message "Source is read-only")) ; (barf-if-buffer-read-only) + (activate-mark)) + ;; Remove the original text from source buffer like + ;; operation `cut'. + (delete-region (overlay-start mouse-secondary-overlay) + (overlay-end mouse-secondary-overlay))) (select-window window1)))) (delete-overlay mouse-secondary-overlay))) \f ^ permalink raw reply related [flat|nested] 89+ messages in thread
* RE: mouse-drag-and-drop-region 2017-11-20 13:29 ` mouse-drag-and-drop-region Tak Kunihiro @ 2017-11-20 16:03 ` Drew Adams 2017-11-20 16:09 ` mouse-drag-and-drop-region Alan Schmitt ` (2 more replies) 2017-11-21 9:24 ` mouse-drag-and-drop-region martin rudalics 1 sibling, 3 replies; 89+ messages in thread From: Drew Adams @ 2017-11-20 16:03 UTC (permalink / raw) To: Tak Kunihiro, rudalics, Eli Zaretskii, Alex; +Cc: emacs-devel FWIW, your mails are incomprehensible, to me. A long jumble, with (apparently) no newlines, just one long line. > -----Original Message----- > From: Tak Kunihiro [mailto:tak.kunihiro@gmail.com] > Sent: Monday, November 20, 2017 5:30 AM > To: rudalics@gmx.at; Eli Zaretskii <eliz@gnu.org>; Alex > <agrambot@gmail.com> > Cc: tak.kunihiro@gmail.com; emacs-devel@gnu.org > Subject: Re: mouse-drag-and-drop-region > > I revised mouse-drag-and-drop-region. I'm sending replay > tohttps://urldefense.proofpoint.com/v2/url?u=https- > 3A__lists.gnu.org_archive_html_emacs-2Ddevel_2017- > 2D11_msg00387.html&d=DwIGCQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE > &r=kI3P6ljGv6CTHIKju0jqInF6AOwMCYRDQUmqX22rJ98&m=7dAC1SXS16w1t_k03RCaPT4y > x9Dj2w0sgzE9HrhKdH4&s=i_DYhSyvTHRfqzR6fFgh4X_gjdsRoGvmXF4Fq-z- > eEU&e=,ChangeLog, and patch.* ChangeLog2017-11-21 Tak Kunihiro > <tkk@misasa.okayama-u.ac.jp> Improve comments and have two new > options * lisp/mouse.el (mouse-drag-and-drop-region): Make tooltip > preview to be an option. Have an option to make dragging cut among > buffers. (mouse-drag-and-drop-region-cut-among-buffer): New flag. > When t, text is cut instead of copy when dragged among buffers. > (mouse-drag-and-drop-region-show-tooltip): New flag. When t, text is > shown by a tooltip in a graphic display.* Replay> Did you ever consider > using the "r" interactive switch instead of the> "e" one?I suppose you > suggest something like below. I cannot make this work.Thus this > revision, I do not use "r" interactive switch.(defun mouse-drag-and-drop- > region (event start and) (interactive "e\nr") ...)>>> (2) Activating > the secondary overlay can be distracting and should>>> be made > optional (facultatively keeping the primary overlay in>>> place > provided (4) below is done).>>>> Region on the other window is not > visible. Thus original region>> should be hi-lighted somehow. Since > mouse-drag-and-drop-region is>> located on mouse.el, mouse-secondary- > overlay was used.>> You mean that you highlight the original region with > the secondary> overlay so that the overlay shows up on the target window > as well and> the user is informed that dropping there might lead to say > "dubious"> results?I think yes. Also, since value-selection would be > inserted before thepoint and mark, I thought it is handy to keep track > where was theregion by an overlay.> I mean something like>> (defcustom > mouse-drag-and-drop-region-show-secondary-overlay t ...)>> where setting > this to nil means to just not show any overlay. And> your code would > have to accept that there is no secondary overlay at> the time of the > drop.I found this takes significant time. I skip to get rid of usage > ofsecondary-overlay on this revision.>>> (3) Showing tooltips can be > distracting and should be optional.>>> Note also, that usurping > tooltips this way may prevent them from>>> showing interesting > properties of the drop area like whether the>>> text there is read > only. OTOH we might consider retaining>>> properties of the text in > (non-GTK) tooltips.>>> I would say>> (defcustom mouse-drag-and-drop- > region-show-tooltip t)>> and never show a tooltip on text-only terminals > even if this is t.OK.>>> (4) The (deactivate-mark) and (mouse-set-point > event) trick to allow>>> showing point the way ?mouse-drag-track? > does can be distracting>>> and should be made optional.>>>> I think > that this is very related to 2, 3, and 5 (as you inferred).>> Yes. It's > irritating to drag a block cursor with the mouse. Do you> know of any > other applications which do such a thing?I cannot think of a way to show > insert point besides (mouse-set-pointevent). Do you suggest overlay-put > "|" or change cursor-type to 'barduring drag? I thought who prefers bar > changes the default cursoranyway. I did not revise code in this > respect.>>> (5) The mouse pointer shape should take care of indicating > the exact>>> position where the drop occurs. We should probably also > signal>>> whenever the current drop position is invalid. This is > IIUC>>> usual practice on most window systems now.>>>> I think it is > a good idea.>> We probably need to define additional cursors for this so > it's not for> Emacs 26.I did not revise code in this aspect.>>> (7) IMO > either cutting should be the default too when the drop>>> occurs in a > different buffer or copying would be the default and>>> pressing the > modifier should produce a cut instead. The current>>> behavior wants > me to always keep in mind whether the target>>> buffer is the same as > the source buffer. At least, this>>> behavior should be made > optional.>>>> Default behavior followed that of file browser on `drag' a > file.>> Which file browser?Finder on macOS and File Explorer on Windows > 10 behave like that way.>> Between the same volume (buffer), `drag' does > `cut' instead of `copy'.>> I prefer current behavior as default but > have>> no objection to have option something like>> (defvar mouse-drag- > and-drop-region-cut-hungry t)>> I would be more radical with>> (defcustom > mouse-drag-and-drop-region-cut-or-copy t)>> where the values 'cut and > 'copy would always categorically cut or copy> (unless the value of > 'mouse-drag-and-drop-region' implies to copy> instead of cut) and t means > your original behavior.A new option was created. Now `cut' can be > default even amongbuffers.(defvar mouse-drag-and-drop-region-cut-among- > buffer nil "When t, text is cut instead of copy when dragged among > buffers.")>>> (8) Read-only text should be handled. An attempt to drop > text into>>> a read-only area should be signalled to the user. An > attempt to>>> cut text from a read-only text/buffer should be > signalled as>>> well.>>>>> For the latter, we copy text instead (cf > C-w in read-only text). So>>> I think this feature should behave > similarly, at least by default.>>>>> I just noticed that the code does > use ?kill-region? already. This>>> has the side-effect of putting the > text into the kill ring,>>> something which should be documented at > least. But I think the code>>> should rather use ?delete-region? instead > with the behavior you>>> proposed.>>>> I suppose that you suggest to tell > user more explicitly in echo area>> how he cannot change the text.>> The > echo area should be avoided during tracking. Think of users who> invoke > 'mouse-drag-and-drop-region' on a frame without a minibuffer.OK.> I think > that first of all you should use 'delete-region' instead of> 'kill- > region' to avoid the above-mentioned side effect. Then your> code should > silently swallow any bugs for cutting from read-only> text provided > 'kill-read-only-ok' is t. For that purpose, simply> peruse the > corresponding code from 'kill-region'.OK. Now `delete-region' is used.> > A final drop into read-only text should always give an error. We> should > be able to redeem that by providing a feedback in form of a> mouse cursor > when the mouse is either over read-only text or no> buffer text at all.I > revised only to give message. I could not tell how to bringcondition- > case to code.>> On an user perspective, operation `drag-and-drop-region' > is a>> combination of `cut' and `paste'. Thus text was killed instead > of>> deleted. How you think delete is more preferred? I have no>> > objection to document it.> IMO using 'kill-region' is an unexpected side > effect. If people> think differently, we could add yet another option > like>> (defucstom mouse-drag-and-drop-region-cut-does-kill-region t)Now > `delete-region' is used instead of `kill-region'.* Patchdiff --git > a/lisp/mouse.el b/lisp/mouse.elold mode 100644new mode 100755index > 17d1732..08f70d4--- a/lisp/mouse.el+++ b/lisp/mouse.el@@ -2361,6 +2361,12 > @@ text is copied instead of being cut." :version "26.1" :group > 'mouse) +(defvar mouse-drag-and-drop-region-cut-among-buffer nil+ "When > t, text is cut instead of copy when dragged among buffers.")++(defvar > mouse-drag-and-drop-region-show-tooltip t+ "When t, text is shown by a > tooltip in a graphic display.")+ (defun mouse-drag-and-drop-region > (event) "Move text in the region to point where mouse is dragged to. > The transportation of text is also referred as `drag and drop'.@@ - > 2369,64 +2375,98 @@ modifier key was pressed when dropping, and the value > of the variable `mouse-drag-and-drop-region' is that modifier, the text > is copied instead of being cut." (interactive "e")- (require > 'tooltip)- (let ((start (region-beginning))+ (let ((mouse-drag-and- > drop-region-show-tooltip+ (and mouse-drag-and-drop-region-show- > tooltip+ (display-multi-frame-p)+ (require > 'tooltip)))+ (start (region-beginning)) (end (region-end)) > (point (point)) (buffer (current-buffer)) (window > (selected-window))- value-selection)+ no-modifier-on-drop+ > value-selection) ; This remains nil when event was "click". > (track-mouse- ;; When event was click instead of drag, skip loop+ > ;; When event was "click" instead of "drag", skip loop. (while > (progn (setq event (read-event)) (or > (mouse-movement-p event) ;; Handle `mouse-autoselect- > window'. (eq (car-safe event) 'select-window)))- > (unless value-selection ; initialization+ ;; Obtain the text in > region. When the loop was skipped,+ ;; value-selection remains > nil.+ (unless value-selection (delete-overlay mouse- > secondary-overlay) (setq value-selection (buffer-substring > start end)) (move-overlay mouse-secondary-overlay start end)) ; > (deactivate-mark)- (ignore-errors (deactivate-mark) ; care > existing region in other window- (mouse-set-point > event)- (tooltip-show value-selection)))- > (tooltip-hide))- ;; Do not modify buffer under mouse when "event was > click",- ;; "drag negligible", > or- ;; "drag to read-only".- > (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; > "event was click"- (member 'secondary-selection ; "drag > negligible"- (mapcar (lambda (xxx) (overlay-get xxx > 'face))- (overlays-at (posn-point (event-end > event)))))- buffer-read-only)- ;; Do not modify buffer > under mouse.+ (ignore-errors+ (deactivate-mark) ; > Maintain region in other window.+ (mouse-set-point event)+ > (when mouse-drag-and-drop-region-show-tooltip+ (tooltip-show > value-selection))))+ ;; Check if modifier was pressed on drop.+ > (setq no-modifier-on-drop+ (not (member mouse-drag-and-drop- > region (event-modifiers event))))+ (when mouse-drag-and-drop-region- > show-tooltip (tooltip-hide)))+ ;; Do not modify buffer under mouse > when event is "click", "drag+ ;; but negligible", or "drag to read- > only". Operation "drag but+ ;; negligible" is defined as drag-and- > drop the text to+ ;; secondary-selection without modifier pressed. > When pressed,+ ;; the text will be inserted to inside of secondary- > selection.+ (if (or (equal (mouse-posn-property (event-end event) > 'face) 'region) ; "click"+ (and (member 'secondary-selection ; > "drag but negligible"+ (mapcar (lambda (xxx) > (overlay-get xxx 'face))+ (overlays-at > (posn-point (event-end event)))))+ no-modifier-on-drop)+ > buffer-read-only) ; "drag to read-only" (cond- > ;; "drag negligible" or "drag to read-only", restore region.+ ;; > Set back the original text as region on "drag but negligible"+ ;; > or "drag to read-only". (value-selection- (select- > window window) ; In case miss drag to other window+ (if buffer- > read-only (message "Buffer is read-only")) ; (barf-if-buffer-read-only)+ > (select-window window) ; Select the source windows back on miss-drag to > other window. (goto-char point) (setq deactivate-mark > nil) (activate-mark))- ;; "event was click"+ ;; > Move point within region on "click". (t (deactivate- > mark) (mouse-set-point event)))- ;; Modify buffer under > mouse by inserting text.+ ;; Intert the text to destination buffer > under mouse. (push-mark) (insert value-selection)- (when > (not (equal (mark) (point))) ; on success insert+ ;; On success, set > the text as region on destination buffer.+ (when (not (equal (mark) > (point))) (setq deactivate-mark nil)- (activate-mark)) ; > have region on destination- ;; Take care of initial region on > source.- (if (equal (current-buffer) buffer) ; when same buffer- > (let (deactivate-mark) ; remove text- (unless (member mouse- > drag-and-drop-region (event-modifiers event))- (kill-region > (overlay-start mouse-secondary-overlay)- > (overlay-end mouse-secondary-overlay))))- (let ((window1 > (selected-window))) ; when beyond buffer- (select-window > window)- (goto-char point) ; restore point on source window- > (activate-mark) ; restore region+ (activate-mark))+ ;; Set > back the original text as region or delete the original+ ;; text on > source buffer.+ (if (equal (current-buffer) buffer)+ ;; > When source buffer and destination buffer are the same,+ ;; > remove the original text.+ (let (deactivate-mark)+ > (if no-modifier-on-drop+ (delete-region (overlay-start > mouse-secondary-overlay)+ (overlay-end > mouse-secondary-overlay))))+ ;; When source buffer and destination > buffer are different,+ ;; keep (set back the original text as > region) or remove the+ ;; original text.+ (let ((window1 > (selected-window)))+ (select-window window) ; Select window > with source buffer.+ (goto-char point) ; Move point to the > original text on source buffer.+ (if (or (if no-modifier-on- > drop+ (not mouse-drag-and-drop-region-cut-among- > buffer)+ mouse-drag-and-drop-region-cut-among-buffer)+ > buffer-read-only)+ ;; Set back the original text as region > on source buffer+ ;; like operation `copy'.+ > (progn+ (if buffer-read-only (message "Source is read- > only")) ; (barf-if-buffer-read-only)+ (activate-mark))+ > ;; Remove the original text from source buffer like+ ;; > operation `cut'.+ (delete-region (overlay-start mouse- > secondary-overlay)+ (overlay-end mouse- > secondary-overlay))) (select-window window1)))) (delete- > overlay mouse-secondary-overlay))) ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-20 16:03 ` mouse-drag-and-drop-region Drew Adams @ 2017-11-20 16:09 ` Alan Schmitt 2017-11-20 17:34 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-20 18:17 ` mouse-drag-and-drop-region Paul Eggert 2 siblings, 0 replies; 89+ messages in thread From: Alan Schmitt @ 2017-11-20 16:09 UTC (permalink / raw) To: emacs-devel [-- Attachment #1: Type: text/plain, Size: 359 bytes --] On 2017-11-20 08:03, Drew Adams <drew.adams@oracle.com> writes: > FWIW, your mails are incomprehensible, to me. A long > jumble, with (apparently) no newlines, just one long line. They look good here (using gnus). Best, Alan -- OpenPGP Key ID : 040D0A3B4ED2E5C7 Monthly Athmospheric CO₂, Mauna Loa Obs. 2017-10: 403.64, 2016-10: 401.57 [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 528 bytes --] ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-20 16:03 ` mouse-drag-and-drop-region Drew Adams 2017-11-20 16:09 ` mouse-drag-and-drop-region Alan Schmitt @ 2017-11-20 17:34 ` Eli Zaretskii 2017-11-20 18:17 ` mouse-drag-and-drop-region Paul Eggert 2 siblings, 0 replies; 89+ messages in thread From: Eli Zaretskii @ 2017-11-20 17:34 UTC (permalink / raw) To: Drew Adams; +Cc: rudalics, tak.kunihiro, agrambot, emacs-devel > Date: Mon, 20 Nov 2017 08:03:41 -0800 (PST) > From: Drew Adams <drew.adams@oracle.com> > Cc: emacs-devel@gnu.org > > FWIW, your mails are incomprehensible, to me. A long > jumble, with (apparently) no newlines, just one long line. May I suggest to change your MUA? Those emails are perfectly legible in Emacs's Rmail, for example. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-20 16:03 ` mouse-drag-and-drop-region Drew Adams 2017-11-20 16:09 ` mouse-drag-and-drop-region Alan Schmitt 2017-11-20 17:34 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-20 18:17 ` Paul Eggert 2 siblings, 0 replies; 89+ messages in thread From: Paul Eggert @ 2017-11-20 18:17 UTC (permalink / raw) To: Drew Adams, Tak Kunihiro; +Cc: emacs-devel On 11/20/2017 08:03 AM, Drew Adams wrote: > FWIW, your mails are incomprehensible, to me. A long > jumble, with (apparently) no newlines, just one long line. You might try switching to a better mailer, since the mail is in a standard format, namely Content-Type: Text/Plain; charset=iso-8859-7 (Latin/Greek), Content-Transfer-Encoding: base64. I decoded it by hand and it looks fine, so it appears that the problem is on your end. Perhaps you can save the mail to a file, and then use Gnus or Rmail to read the file, since they can handle the format. Your mailer identifies itself as "Oracle Beehive Extensions for Outlook 2.0.1.9.1 (1003210) [OL 16.0.4615.0 (x86)]", so another possibility is for you to fix your mailer's bug yourself, or ask one of your colleagues at Oracle to fix it. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-20 13:29 ` mouse-drag-and-drop-region Tak Kunihiro 2017-11-20 16:03 ` mouse-drag-and-drop-region Drew Adams @ 2017-11-21 9:24 ` martin rudalics 2017-11-21 13:09 ` mouse-drag-and-drop-region Stefan Monnier ` (3 more replies) 1 sibling, 4 replies; 89+ messages in thread From: martin rudalics @ 2017-11-21 9:24 UTC (permalink / raw) To: Tak Kunihiro, Eli Zaretskii, Alex; +Cc: emacs-devel >> Did you ever consider using the "r" interactive switch instead of the >> "e" one? > > I suppose you suggest something like below. I cannot make this work. > Thus this revision, I do not use "r" interactive switch. > > (defun mouse-drag-and-drop-region (event start and) > (interactive "e\nr") > ...) We would probably have to change 'mouse-drag-region' for that to work. >> I mean something like >> >> (defcustom mouse-drag-and-drop-region-show-secondary-overlay t ...) >> >> where setting this to nil means to just not show any overlay. And >> your code would have to accept that there is no secondary overlay at >> the time of the drop. > > I found this takes significant time. I skip to get rid of usage of > secondary-overlay on this revision. What takes significant time? Please elaborate. > I cannot think of a way to show insert point besides (mouse-set-point > event). Do you suggest overlay-put "|" or change cursor-type to 'bar > during drag? I thought who prefers bar changes the default cursor > anyway. I did not revise code in this respect. I think that using 'mouse-set-point' as we do for 'mouse-drag-track' is not necessarily a good idea. The idea with 'mouse-drag-track' is that its user usually wants point to go where the mouse moves. The idea with 'mouse-drag-and-drop-region' is that the user wants to drop text where the mouse goes but not necessarily also move point there. If we want 'mouse-drag-and-drop-region' to do additional things (like killing the region or moving point) we should make these customizable at least. >>>> (7) IMO either cutting should be the default too when the drop >>>> occurs in a different buffer or copying would be the default and >>>> pressing the modifier should produce a cut instead. The current >>>> behavior wants me to always keep in mind whether the target >>>> buffer is the same as the source buffer. At least, this >>>> behavior should be made optional. >>> >>> Default behavior followed that of file browser on `drag' a file. >> >> Which file browser? > > Finder on macOS and File Explorer on Windows 10 behave like that way. Do you mean that they move a file when the target directories differ and copy it when they are the same? Isn't that then the opposite of >>> Between the same volume (buffer), `drag' does `cut' instead of `copy'. In either case I fail to see the volume/buffer connection relationship. But maybe that's just me. >> I think that first of all you should use 'delete-region' instead of >> 'kill-region' to avoid the above-mentioned side effect. Then your >> code should silently swallow any bugs for cutting from read-only >> text provided 'kill-read-only-ok' is t. For that purpose, simply >> peruse the corresponding code from 'kill-region'. > > OK. Now `delete-region' is used. As mentioned, we can always add an option to kill the region instead. > I revised only to give message. I could not tell how to bring > condition-case to code. IMO this is one of the two major things to fix before the release. Think of someone using this function in a way you didn't anticipate (for example, take the bug mentioned by Alex that someone hits some other key while dragging). If mouse tracking then throws an error and you changed point or the region or leave the secondary overlay around, this can be very irritating. After all, we want people to have a smooth experience especially when using a new function. Obviously, if you do not move point, do not create a secondary overlay or do not change the region, these are not needed. Otherwise, the function should restore the entire configuration (selected window, point, region, overlays at least) that existed before dragging started so that the user can restart from there. More precisely, you should wrap 'track-mouse' and whatever you do after it terminates in a 'condition-case' form and in the error part restore everything to the saved values. Like so: (... ; save the state here (condition-case nil (progn (track-mouse ) ) (error ... ; restore the state here ))) If you have any problems coding that, please ask. > +(defvar mouse-drag-and-drop-region-cut-among-buffer nil > + "When t, text is cut instead of copy when dragged among buffers.") This should be a 'defcustom'. I would write instead (defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil "If non-nil, cut text also when source and destination buffers differ. If this option is nil, `mouse-drag-and-drop-region' will leave the text in the source buffer alone when dropping it in a different buffer. If this is non-nil, it will cut the text just as it does when dropping text in the source buffer." :type 'boolean :version "27.1" :group 'mouse) and likewise for 'mouse-drag-and-drop-region-show-tooltip' (note also the use of active voice and non-nil instead of t). > + (when mouse-drag-and-drop-region-show-tooltip > + (tooltip-show value-selection)))) Still not quite right: Never show a tooltip on text-only frames. Think of people who want to show tooltips but occasionally work on TTYs. > + (if buffer-read-only (message "Buffer is read-only")) ; (barf-if-buffer-read-only) 'buffer-read-only' is not sufficient. Please handle read-only text properties at this position. > + ;; Intert the text to destination buffer under mouse. ^ > + (let ((window1 (selected-window))) > + (select-window window) ; Select window with source buffer. > + (goto-char point) ; Move point to the original text on source buffer. [...] > (select-window window1)))) I think (set-window-point window point) instead of the above should suffice. And if I'm not mistaken you still disallow to copy text into itself. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-21 9:24 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-21 13:09 ` Stefan Monnier 2017-11-21 14:05 ` mouse-drag-and-drop-region martin rudalics 2017-11-21 15:45 ` mouse-drag-and-drop-region Eli Zaretskii ` (2 subsequent siblings) 3 siblings, 1 reply; 89+ messages in thread From: Stefan Monnier @ 2017-11-21 13:09 UTC (permalink / raw) To: emacs-devel > I think that using 'mouse-set-point' as we do for 'mouse-drag-track' is > not necessarily a good idea. Hmm... mouse-drag-track does not mouse-set-point nowadays (it just highlights the text while you drag the mouse, but what happens when you finally release the button is determined by the normal keymap bindings). Stefan ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-21 13:09 ` mouse-drag-and-drop-region Stefan Monnier @ 2017-11-21 14:05 ` martin rudalics 2017-11-21 19:07 ` mouse-drag-and-drop-region Stefan Monnier 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-11-21 14:05 UTC (permalink / raw) To: Stefan Monnier, emacs-devel > Hmm... mouse-drag-track does not mouse-set-point nowadays (it just > highlights the text while you drag the mouse, IIUC it uses 'mouse-set-point' initially and 'mouse--drag-set-mark-and-point' while dragging. > but what happens when you > finally release the button is determined by the normal keymap bindings). Sure. But the idea is that it synchronizes point with the mouse position till then. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-21 14:05 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-21 19:07 ` Stefan Monnier 2017-11-22 8:26 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Stefan Monnier @ 2017-11-21 19:07 UTC (permalink / raw) To: martin rudalics; +Cc: emacs-devel >> but what happens when you >> finally release the button is determined by the normal keymap bindings). > Sure. But the idea is that it synchronizes point with the mouse > position till then. Indeed. It should probably be generalized for uses where that's not appropriate (similarly for uses where the mark shouldn't be modified (not even temporarily)). E.g. for mouse-drag-secondary. Stefan ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-21 19:07 ` mouse-drag-and-drop-region Stefan Monnier @ 2017-11-22 8:26 ` martin rudalics 2017-11-22 21:20 ` mouse-drag-and-drop-region Stefan Monnier 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-11-22 8:26 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > Indeed. It should probably be generalized for uses where that's not > appropriate (similarly for uses where the mark shouldn't be modified > (not even temporarily)). E.g. for mouse-drag-secondary. Tracking the mouse and keeping the region intact is impossible unless we continuously synchronize the position of point and the mouse cursor. Anything else would invalidate the region as soon as scrolling the window moves point. So unless we allow alternative semantics of the "region" 'mouse-drag-track' will have to modify the region as it does now. Note in this context that the doc-string of 'mouse-drag-track' "Track mouse drags by highlighting area between point and cursor. The region will be defined with mark and point." is completely misleading. It should start with a line like "Track mouse drags by synchronizing point with the mouse cursor." where we could explain that "synchronizing" means something like moving point to the most nearby buffer position corresponding to the current mouse position on the screen and that dragging leaves the mark unchanged and the highlighted region will change accordingly. Obviously, we can give 'mouse-drag-track' an extra argument which 'mouse-drag-region' (and 'mouse-drag-secondary') would set appropriately to tell it how to handle the region. Before doing that we should, however, establish the canonical way to handle mouse tracking. More precisely, we should decide whether we prefer the 'track-mouse' plus 'read-event' approach or the 'set-transient-map' one. Currently, this doesn't seem entirely clear to me. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-22 8:26 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-22 21:20 ` Stefan Monnier 2017-11-23 7:46 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Stefan Monnier @ 2017-11-22 21:20 UTC (permalink / raw) To: emacs-devel > More precisely, we should decide whether we prefer the 'track-mouse' > plus 'read-event' approach or the 'set-transient-map' one. Currently, > this doesn't seem entirely clear to me. I very clearly vote in favor of set-transient-map, since the use read-event leads inevitably to lots of corner case problems that are in general impossible to fix. Stefan ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-22 21:20 ` mouse-drag-and-drop-region Stefan Monnier @ 2017-11-23 7:46 ` martin rudalics 2017-11-23 14:00 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-23 16:09 ` mouse-drag-and-drop-region Eli Zaretskii 0 siblings, 2 replies; 89+ messages in thread From: martin rudalics @ 2017-11-23 7:46 UTC (permalink / raw) To: Stefan Monnier, emacs-devel > I very clearly vote in favor of set-transient-map, since the use > read-event leads inevitably to lots of corner case problems that are in > general impossible to fix. Actually, this boils down to marking `track-mouse' obsolete in a not so distant future. Additionally, `mouse-drag-track' should be renamed once more - to something like `mouse-drag-within-window' - the distinguishing factor being that all events are interpreted relative to the window of the starting event. And we should provide a `mouse-drag-anywhere' function which, among others, does not auto scroll the window of the starting event. Hence `mouse-drag-and-drop-region' could use the latter. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-23 7:46 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-23 14:00 ` Stefan Monnier 2017-11-23 16:09 ` mouse-drag-and-drop-region Eli Zaretskii 1 sibling, 0 replies; 89+ messages in thread From: Stefan Monnier @ 2017-11-23 14:00 UTC (permalink / raw) To: martin rudalics; +Cc: emacs-devel >> I very clearly vote in favor of set-transient-map, since the use >> read-event leads inevitably to lots of corner case problems that are in >> general impossible to fix. > Actually, this boils down to marking `track-mouse' obsolete in a not so > distant future. You mean the special-form, right? Because the variable is still very much needed. Yes, for me we can mark it obsolete. > Additionally, `mouse-drag-track' should be renamed once > more - to something like `mouse-drag-within-window' - the distinguishing > factor being that all events are interpreted relative to the window of > the starting event. And we should provide a `mouse-drag-anywhere' > function which, among others, does not auto scroll the window of the > starting event. Hence `mouse-drag-and-drop-region' could use the latter. Actually, maybe mouse-drag-and-drop-region could also make use of a generalized version of mouse-drag-track. Stefan ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-23 7:46 ` mouse-drag-and-drop-region martin rudalics 2017-11-23 14:00 ` mouse-drag-and-drop-region Stefan Monnier @ 2017-11-23 16:09 ` Eli Zaretskii 2017-11-24 9:02 ` mouse-drag-and-drop-region martin rudalics 1 sibling, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-23 16:09 UTC (permalink / raw) To: martin rudalics; +Cc: monnier, emacs-devel > Date: Thu, 23 Nov 2017 08:46:52 +0100 > From: martin rudalics <rudalics@gmx.at> > > > I very clearly vote in favor of set-transient-map, since the use > > read-event leads inevitably to lots of corner case problems that are in > > general impossible to fix. > > Actually, this boils down to marking `track-mouse' obsolete in a not so > distant future. If we do, what will replace it? ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-23 16:09 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-24 9:02 ` martin rudalics 2017-11-24 9:19 ` mouse-drag-and-drop-region Eli Zaretskii 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-11-24 9:02 UTC (permalink / raw) To: Eli Zaretskii; +Cc: monnier, emacs-devel >> Actually, this boils down to marking `track-mouse' obsolete in a not so >> distant future. > > If we do, what will replace it? Something based on the transient keymap paradigm. Whether that will be a macro or some rule to suitably set/restore `track-mouse' around a call of `set-transient-map'. But I only draw conclusion from arguments against using `read-event' (maybe in the context of mouse tracking only) which I yet don't fully understand. And I also don't understand whether an unprotected (re-)setting of `track-mouse' is safe wrt redisplay but maybe you can clarify that. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-24 9:02 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-24 9:19 ` Eli Zaretskii 2017-11-24 9:41 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-24 9:19 UTC (permalink / raw) To: martin rudalics; +Cc: monnier, emacs-devel > Date: Fri, 24 Nov 2017 10:02:08 +0100 > From: martin rudalics <rudalics@gmx.at> > CC: monnier@iro.umontreal.ca, emacs-devel@gnu.org > > >> Actually, this boils down to marking `track-mouse' obsolete in a not so > >> distant future. > > > > If we do, what will replace it? > > Something based on the transient keymap paradigm. Obsoleting such a veteran feature needs a very good reason, because it causes annoyances across the community, as it's most probably is used in a lot of places outside of the Emacs tree. If the only reason we have is that there are some disadvantages in some corner cases, it's not enough to obsolete the form, IMO. > And I also don't understand whether an unprotected (re-)setting of > `track-mouse' is safe wrt redisplay but maybe you can clarify that. Why would it be unsafe wrt redisplay? ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-24 9:19 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-24 9:41 ` martin rudalics 2017-11-24 13:25 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-24 13:45 ` mouse-drag-and-drop-region Eli Zaretskii 0 siblings, 2 replies; 89+ messages in thread From: martin rudalics @ 2017-11-24 9:41 UTC (permalink / raw) To: Eli Zaretskii; +Cc: monnier, emacs-devel > Obsoleting such a veteran feature needs a very good reason, because it > causes annoyances across the community, as it's most probably is used > in a lot of places outside of the Emacs tree. If the only reason we > have is that there are some disadvantages in some corner cases, it's > not enough to obsolete the form, IMO. Yes. I already said that I don't fully understand the arguments against `read-event'. > Why would it be unsafe wrt redisplay? Because of that part of tracking_off: /* Redisplay may have been preempted because there was input available, and it assumes it will be called again after the input has been processed. If the only input available was the sort that we have just disabled, then we need to call redisplay. */ if (!readable_events (READABLE_EVENTS_DO_TIMERS_NOW)) { redisplay_preserve_echo_area (6); get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW); } IIUC we don't do that in `mouse-drag-track'. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-24 9:41 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-24 13:25 ` Stefan Monnier 2017-11-26 10:24 ` mouse-drag-and-drop-region martin rudalics 2017-11-24 13:45 ` mouse-drag-and-drop-region Eli Zaretskii 1 sibling, 1 reply; 89+ messages in thread From: Stefan Monnier @ 2017-11-24 13:25 UTC (permalink / raw) To: emacs-devel > Yes. I already said that I don't fully understand the arguments against > `read-event'. There's no problem with read-event itself. The problems is that you can't reliably *un*read an event, so the arguments are against uses of read-event that just "peek" at the next event without the intention to fully consume it. Stefan ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-24 13:25 ` mouse-drag-and-drop-region Stefan Monnier @ 2017-11-26 10:24 ` martin rudalics 0 siblings, 0 replies; 89+ messages in thread From: martin rudalics @ 2017-11-26 10:24 UTC (permalink / raw) To: Stefan Monnier, emacs-devel > There's no problem with read-event itself. The problems is that you > can't reliably *un*read an event, so the arguments are against uses of > read-event that just "peek" at the next event without the intention to > fully consume it. Couldn't you then write up some text that tells us about the pitfalls of unreading an event and what should be done instead? All I found in the Elisp manual is: The reliable and easy way to extract events from a key sequence so as to put them in `unread-command-events' is to use `listify-key-sequence' (see below). but I see no explanation how `unread-command-events' can be updated safely after a `read-event' and whether/when that should be avoided. Pretty please, martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-24 9:41 ` mouse-drag-and-drop-region martin rudalics 2017-11-24 13:25 ` mouse-drag-and-drop-region Stefan Monnier @ 2017-11-24 13:45 ` Eli Zaretskii 2017-11-26 10:24 ` mouse-drag-and-drop-region martin rudalics 1 sibling, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-24 13:45 UTC (permalink / raw) To: martin rudalics; +Cc: monnier, emacs-devel > Date: Fri, 24 Nov 2017 10:41:12 +0100 > From: martin rudalics <rudalics@gmx.at> > CC: monnier@iro.umontreal.ca, emacs-devel@gnu.org > > > Why would it be unsafe wrt redisplay? > > Because of that part of tracking_off: > > /* Redisplay may have been preempted because there was input > available, and it assumes it will be called again after the > input has been processed. If the only input available was > the sort that we have just disabled, then we need to call > redisplay. */ > if (!readable_events (READABLE_EVENTS_DO_TIMERS_NOW)) > { > redisplay_preserve_echo_area (6); > get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW); > } With redisplay-dont-pause being t by default, this shouldn't happen unless someone customizes that option. > IIUC we don't do that in `mouse-drag-track'. Why should we? mouse-drag-track works via the normal command loop machinery. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-24 13:45 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-26 10:24 ` martin rudalics 2017-11-26 15:54 ` mouse-drag-and-drop-region Eli Zaretskii 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-11-26 10:24 UTC (permalink / raw) To: Eli Zaretskii; +Cc: monnier, emacs-devel >> IIUC we don't do that in `mouse-drag-track'. > > Why should we? mouse-drag-track works via the normal command loop > machinery. Which can only process or ignore but never postpone events? martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-26 10:24 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-26 15:54 ` Eli Zaretskii 2017-11-27 8:48 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-26 15:54 UTC (permalink / raw) To: martin rudalics; +Cc: monnier, emacs-devel > Date: Sun, 26 Nov 2017 11:24:50 +0100 > From: martin rudalics <rudalics@gmx.at> > CC: monnier@iro.umontreal.ca, emacs-devel@gnu.org > > >> IIUC we don't do that in `mouse-drag-track'. > > > > Why should we? mouse-drag-track works via the normal command loop > > machinery. > > Which can only process or ignore but never postpone events? Which is not different from keyboard input, and therefore doesn't need special handling or consideration, AFAIU. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-26 15:54 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-27 8:48 ` martin rudalics 2017-11-27 15:59 ` mouse-drag-and-drop-region Eli Zaretskii 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-11-27 8:48 UTC (permalink / raw) To: Eli Zaretskii; +Cc: monnier, emacs-devel >> Which can only process or ignore but never postpone events? > > Which is not different from keyboard input, and therefore doesn't need > special handling or consideration, AFAIU. That's what I meant. Now `mouse-drag-track' does two essential things: It sets `track-mouse' to non-nil so mouse movement creates input events and it uses a transient keymap to process them. However, an application that wants to look into an event and postpone it via "unreading" it, is still able to do so, right? So the only difference to using the `track-mouse' macro is that the transient keymap approach obfuscates the underlying event reading mechanism and thus does not overtly invite the application to unread events. Is that interpretation correct? martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-27 8:48 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-27 15:59 ` Eli Zaretskii 0 siblings, 0 replies; 89+ messages in thread From: Eli Zaretskii @ 2017-11-27 15:59 UTC (permalink / raw) To: martin rudalics; +Cc: monnier, emacs-devel > Date: Mon, 27 Nov 2017 09:48:44 +0100 > From: martin rudalics <rudalics@gmx.at> > CC: monnier@iro.umontreal.ca, emacs-devel@gnu.org > > That's what I meant. Now `mouse-drag-track' does two essential things: > It sets `track-mouse' to non-nil so mouse movement creates input events > and it uses a transient keymap to process them. However, an application > that wants to look into an event and postpone it via "unreading" it, is > still able to do so, right? So the only difference to using the > `track-mouse' macro is that the transient keymap approach obfuscates the > underlying event reading mechanism and thus does not overtly invite the > application to unread events. Is that interpretation correct? I think so, but I'm not an expert on this stuff. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-21 9:24 ` mouse-drag-and-drop-region martin rudalics 2017-11-21 13:09 ` mouse-drag-and-drop-region Stefan Monnier @ 2017-11-21 15:45 ` Eli Zaretskii 2017-11-22 8:22 ` mouse-drag-and-drop-region martin rudalics 2017-11-21 18:52 ` mouse-drag-and-drop-region Robert Weiner 2017-11-23 23:28 ` mouse-drag-and-drop-region Tak Kunihiro 3 siblings, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-11-21 15:45 UTC (permalink / raw) To: martin rudalics; +Cc: tak.kunihiro, agrambot, emacs-devel > Date: Tue, 21 Nov 2017 10:24:26 +0100 > From: martin rudalics <rudalics@gmx.at> > CC: emacs-devel@gnu.org > > > +(defvar mouse-drag-and-drop-region-cut-among-buffer nil > > + "When t, text is cut instead of copy when dragged among buffers.") > > This should be a 'defcustom'. I would write instead > > (defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil > "If non-nil, cut text also when source and destination buffers differ. > If this option is nil, `mouse-drag-and-drop-region' will leave > the text in the source buffer alone when dropping it in a > different buffer. If this is non-nil, it will cut the text just > as it does when dropping text in the source buffer." > :type 'boolean > :version "27.1" "26.1", I should expect. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-21 15:45 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-22 8:22 ` martin rudalics 0 siblings, 0 replies; 89+ messages in thread From: martin rudalics @ 2017-11-22 8:22 UTC (permalink / raw) To: Eli Zaretskii; +Cc: tak.kunihiro, agrambot, emacs-devel >> :version "27.1" > > "26.1", I should expect. Let's hope for the best. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-21 9:24 ` mouse-drag-and-drop-region martin rudalics 2017-11-21 13:09 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-21 15:45 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-11-21 18:52 ` Robert Weiner 2017-11-22 8:22 ` mouse-drag-and-drop-region martin rudalics 2017-11-23 23:28 ` mouse-drag-and-drop-region Tak Kunihiro 3 siblings, 1 reply; 89+ messages in thread From: Robert Weiner @ 2017-11-21 18:52 UTC (permalink / raw) To: martin rudalics; +Cc: Eli Zaretskii, Tak Kunihiro, Alex, emacs-devel [-- Attachment #1: Type: text/plain, Size: 815 bytes --] On Tue, Nov 21, 2017 at 4:24 AM, martin rudalics <rudalics@gmx.at> wrote: > > (defcustom mouse-drag-and-drop-region-cut-when-buffers-differ A few suggestions. This name is too specific. If such an option is introduced it could just be named mouse-drag-and-drop-region-cut-flag and any limitations could be included in the doc string, as they are already. Then if its behavior were modified in the future, the name would not need changing. But the option, mouse-drag-and-drop-region, already exists and does a bunch of things that control cutting and copying of the dragged region. It would make sense if this setting could somehow be integrated in there (one source of truth) so there were no need to add a boolean just for this one aspect of regional drag and drop. Bob [-- Attachment #2: Type: text/html, Size: 2002 bytes --] ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-21 18:52 ` mouse-drag-and-drop-region Robert Weiner @ 2017-11-22 8:22 ` martin rudalics 0 siblings, 0 replies; 89+ messages in thread From: martin rudalics @ 2017-11-22 8:22 UTC (permalink / raw) To: rswgnu; +Cc: Eli Zaretskii, Tak Kunihiro, Alex, emacs-devel >> (defcustom mouse-drag-and-drop-region-cut-when-buffers-differ > > > A few suggestions. This name is too specific. If such an option is > introduced it could just be named > mouse-drag-and-drop-region-cut-flag and any limitations could be included > in the doc string, as they are already. Then > if its behavior were modified in the future, the name would not need > changing. The option could also allow to copy text without having to rely on the modifier key. Then pressing the modifier key could just invert the standard behavior specified by that option. > But the option, mouse-drag-and-drop-region, already exists and does a bunch > of things that control cutting and copying > of the dragged region. It would make sense if this setting could somehow > be integrated in there (one source of truth) > so there were no need to add a boolean just for this one aspect of regional > drag and drop. If the default behavior is different wrt whether the buffers differ, I see no way to avoid an extra option. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-21 9:24 ` mouse-drag-and-drop-region martin rudalics ` (2 preceding siblings ...) 2017-11-21 18:52 ` mouse-drag-and-drop-region Robert Weiner @ 2017-11-23 23:28 ` Tak Kunihiro 2017-11-24 9:02 ` mouse-drag-and-drop-region martin rudalics 3 siblings, 1 reply; 89+ messages in thread From: Tak Kunihiro @ 2017-11-23 23:28 UTC (permalink / raw) To: rudalics; +Cc: eliz, tak.kunihiro, agrambot, emacs-devel Thank you for the replay. >>> I mean something like >>> >>> (defcustom >>> mouse-drag-and-drop-region-show-secondary-overlay t >>> ...) >>> where setting this to nil means to just not show any overlay. And >>> your code would have to accept that there is no secondary overlay >>> at the time of the drop. >> I found this takes significant time. I skip to get rid of usage of >> secondary-overlay on this revision. > > What takes significant time? Please elaborate. I meant I need to spend significant time to make secondary-overlay option. I have started to fix things from easy ones. >> I cannot think of a way to show insert point besides >> (mouse-set-point event). Do you suggest overlay-put "|" or change >> cursor-type to 'bar during drag? I thought who prefers bar changes >> the default cursor anyway. I did not revise code in this respect. > > I think that using 'mouse-set-point' as we do for 'mouse-drag-track' > is not necessarily a good idea. The idea with 'mouse-drag-track' is > that its user usually wants point to go where the mouse moves. The > idea with 'mouse-drag-and-drop-region' is that the user wants to > drop text where the mouse goes but not necessarily also move point > there. If we want 'mouse-drag-and-drop-region' to do additional > things (like killing the region or moving point) we should make > these customizable at least. How to show insert point? Do you mean restore active cursor back to source text? >>>>> (7) IMO either cutting should be the default too when the drop >>>>> occurs in a different buffer or copying would be the default and >>>>> pressing the modifier should produce a cut instead. The current >>>>> behavior wants me to always keep in mind whether the target >>>>> buffer is the same as the source buffer. At least, this >>>>> behavior should be made optional. >>>> >>>> Default behavior followed that of file browser on `drag' a file. >>>> >>> Which file browser? >> >> Finder on macOS and File Explorer on Windows 10 behave like that >> way. > > Do you mean that they move a file when the target directories differ > and copy it when they are the same? Isn't that then the opposite of > >>>> Between the same volume (buffer), `drag' does `cut' instead of >>>> `copy'. > > In either case I fail to see the volume/buffer connection > relationship. But maybe that's just me. When an Icon of c:/runemacs.exe is dragged to d:/, copy. When an Icon of c:/runemacs.exe is dragged to c:/emacs-26.0.90/bin, cut. >> I could not tell how to bring condition-case to code. > > IMO this is one of the two major things to fix before the release. > Think of someone using this function in a way you didn't anticipate > (for example, take the bug mentioned by Alex that someone hits some > other key while dragging). If mouse tracking then throws an error > and you changed point or the region or leave the secondary overlay > around, this can be very irritating. After all, we want people to > have a smooth experience especially when using a new function. ... > (... ; save the state here > (condition-case nil > (progn > (track-mouse > ) > ) > (error ... ; restore the state here > ))) > > If you have any problems coding that, please ask. OK. I will (but not yet). >> +(defvar mouse-drag-and-drop-region-cut-among-buffer >> nil >> + "When t, text is cut instead of copy when dragged >> among buffers.") > This should be a 'defcustom'. I would write instead > > (defcustom > mouse-drag-and-drop-region-cut-when-buffers-differ nil > "If non-nil, cut text also when source and > destination buffers differ. > If this option is nil, `mouse-drag-and-drop-region' > will leave > the text in the source buffer alone when dropping it > in a > different buffer. If this is non-nil, it will cut the > text just > as it does when dropping text in the source buffer." > :type 'boolean > :version "27.1" > :group 'mouse) > > and likewise for > 'mouse-drag-and-drop-region-show-tooltip' (note also > the use of active voice and non-nil instead of t). OK. >> + (when mouse-drag-and-drop-region-show-tooltip >> + (tooltip-show value-selection)))) > Still not quite right: Never show a tooltip on text-only frames. > Think of people who want to show tooltips but occasionally work on > TTYs. I think the patch covered that. The approach is to overwrite mouse-drag-and-drop-region-show-tooltip locally. (let ((mouse-drag-and-drop-region-show-tooltip (and mouse-drag-and-drop-region-show-tooltip (display-multi-frame-p) (require 'tooltip))) >> + (if buffer-read-only (message "Buffer is >> read-only")) ; (barf-if-buffer-read-only) > > 'buffer-read-only' is not sufficient. Please handle > read-only > text properties at this position. OK. >> + (let ((window1 (selected-window))) >> + (select-window window) ; Select window with source >> buffer. >> + (goto-char point) ; Move point to the original >> text on source buffer. > [...] >> (select-window window1)))) > > I think > > (set-window-point window point) > > instead of the above should suffice. To select window is necessary for the case. I try to use it when fits. > And if I'm not mistaken you still disallow to copy > text into itself. I forgot to mention, that was fixed. I think that there are two significant TODOs. - Make drag robust using condition-case - Make secondary-overlay option ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-23 23:28 ` mouse-drag-and-drop-region Tak Kunihiro @ 2017-11-24 9:02 ` martin rudalics 2017-11-27 13:11 ` mouse-drag-and-drop-region Tak Kunihiro 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-11-24 9:02 UTC (permalink / raw) To: Tak Kunihiro; +Cc: eliz, agrambot, emacs-devel > I meant I need to spend significant time to make secondary-overlay > option. I have started to fix things from easy ones. Do you mean that it's difficult to make the code work if it does not use the secondary overlay? I don't understand why, instead of perusing the secondary overlay, you don't use your own overlay to indicate start and end of the text you cut or copy. When done with the operation or when an error occurs during dragging, you simply remove that overlay. In addition, you can define a face the user can customize in order to highlight that overlay. This way, any secondary overlay that existed already when the user started dragging would be just left alone. > How to show insert point? I think that by default the insert point should be shown by the mouse cursor alone. Personally, I'd also prefer that when the original position of point is scrolled off-screen, the normal cursor should not be shown at all because it's by no means sure that it will stay there after the drop occurred: If the drop happens in another buffer, you restore the original point to where it was before. Note that this is not the case with `mouse-drag-region' which always leaves the normal cursor at its last position even after the window was auto-scrolled. Optionally, I see no problem showing the normal cursor just as `mouse-drag-region' does, maybe with some customizable cursor type (I think "bar" would give a better feeling than "box"). > Do you mean restore active cursor back to source text? When an error occurs, definitely so. Then you should do what you do when the drop happens in another buffer. Maybe in these cases you additionally should restore the window start position too, so that the user can start from where she left off. If you restore the window's point only as you do now, then the region will be often partially off-screen (at least here) although it was on-screen before. When everything "goes well", point obviously will go to the position of the inserted text. Although when the drop happens in another window showing the same buffer, it might be interesting to restore the source window's state just as if the drop happened in another buffer. > When an Icon of c:/runemacs.exe is dragged to d:/, copy. When an Icon > of c:/runemacs.exe is dragged to c:/emacs-26.0.90/bin, cut. I see what you mean now but I doubt that many users of `mouse-drag-and-drop-region' will be aware of such an analogy. > I think the patch covered that. The approach is to overwrite > mouse-drag-and-drop-region-show-tooltip locally. > > (let ((mouse-drag-and-drop-region-show-tooltip > (and mouse-drag-and-drop-region-show-tooltip > (display-multi-frame-p) > (require 'tooltip))) You're right. I apparently missed that. > I think that there are two significant TODOs. > - Make drag robust using condition-case Definitely. > - Make secondary-overlay option This would be nice to have. Thank you, martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-24 9:02 ` mouse-drag-and-drop-region martin rudalics @ 2017-11-27 13:11 ` Tak Kunihiro 2017-11-28 8:50 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Tak Kunihiro @ 2017-11-27 13:11 UTC (permalink / raw) To: rudalics; +Cc: eliz, tak.kunihiro, agrambot, emacs-devel I re-revised mouse-drag-and-drop-region. I'm sending replay to https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00589.html, ChangeLog, and patch. * ChangeLog 2017-11-27 Tak Kunihiro <tkk@misasa.okayama-u.ac.jp> Improve comments and have three new options * lisp/mouse.el (mouse-drag-and-drop-region): Make usage of tooltip option. Have option to make dragging cut among buffers. (mouse-drag-and-drop-region-cut-when-buffers-differ): New variable. If non-nil, text is cut instead of copied when dragged among buffers. (mouse-drag-and-drop-region-show-tooltip): New variable. If non-nil, text is shown by tooltip in a graphic display. (mouse-drag-and-drop-region-face): New variable for face. The face is used to highlight the original text. * Replay > instead of perusing the secondary overlay, you don't use your own > overlay to indicate start and end of the text you cut or copy. When > done with the operation or when an error occurs during dragging, you > simply remove that overlay. In addition, you can define a face the > user can customize in order to highlight that overlay. OK. That is a good idea. I got rid of usage of secondary-overlay. I define a new variable mouse-drag-and-drop-region-face. >> How to show insert point? > > I think that by default the insert point should be shown by the > mouse cursor alone. Optionally, I see no problem showing the normal > cursor just as `mouse-drag-region' does, maybe with some > customizable cursor type (I think "bar" would give a better feeling > than "box"). OK. Only set point by mouse-set-point when mouse-drag-and-drop-region-show-tooltip is non-nil with changing cursor type. I also changed the default of mouse-drag-and-drop-region-show-tooltip to nil to be more stable against accident during dragging. > More precisely, you should wrap 'track-mouse' and whatever you do > after it terminates in a 'condition-case' form and in the error part > restore everything to the saved values. Like so: > > (... ; save the state here > (condition-case nil > (progn > (track-mouse > ) > ) > (error ... ; restore the state here > ))) > > If you have any problems coding that, please ask. Even track-mouse is sandwiched by condition-case, I cannot catch a error typing during dragging. However, as inferred already, when mouse-drag-and-drop-region-show-tooltip is nil, it is more stable even typing key during dragging. * Patch diff --git a/lisp/mouse.el b/lisp/mouse.el old mode 100644 new mode 100755 index 17d1732..b81d56e --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -2361,6 +2361,29 @@ text is copied instead of being cut." :version "26.1" :group 'mouse) +(defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil + "If non-nil, cut text also when source and destination buffers differ. +If this option is nil, `mouse-drag-and-drop-region' will leave +the text in the source buffer alone when dropping it in a +different buffer. If this is non-nil, it will cut the text just +as it does when dropping text in the source buffer." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-tooltip nil + "If non-nil, text is shown by a tooltip in a graphic display. +If this option is non-nil, point is set to where the mouse cursor +is during dragging and the original text is highlighted by face +`mouse-drag-and-drop-region-face'." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defvar mouse-drag-and-drop-region-face 'region + "Face to highlight the original text during dragging. +See also `mouse-drag-and-drop-region-show-tooltip'.") + (defun mouse-drag-and-drop-region (event) "Move text in the region to point where mouse is dragged to. The transportation of text is also referred as `drag and drop'. @@ -2369,66 +2392,171 @@ modifier key was pressed when dropping, and the value of the variable `mouse-drag-and-drop-region' is that modifier, the text is copied instead of being cut." (interactive "e") - (require 'tooltip) - (let ((start (region-beginning)) - (end (region-end)) - (point (point)) - (buffer (current-buffer)) - (window (selected-window)) - value-selection) + (let* ((mouse-drag-and-drop-region-show-tooltip + (and mouse-drag-and-drop-region-show-tooltip + (display-multi-frame-p) + (require 'tooltip))) + (start (region-beginning)) + (end (region-end)) + (point (point)) + (buffer (current-buffer)) + (window (selected-window)) + (cursor-type cursor-type) + (text-from-read-only buffer-read-only) + (mouse-drag-and-drop-overlay + (make-overlay start end)) + point-to-paste + point-to-paste-read-only + window-to-paste + no-modifier-on-drop + drag-but-negligible + clicked + value-selection) ; This remains nil when event was "click". + + ;; FIXME: Handle error such as hitting C-g while dragging. See + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00486.html (track-mouse - ;; When event was click instead of drag, skip loop + ;; When event was "click" instead of "drag", skip loop. (while (progn (setq event (read-event)) (or (mouse-movement-p event) ;; Handle `mouse-autoselect-window'. (eq (car-safe event) 'select-window))) - (unless value-selection ; initialization - (delete-overlay mouse-secondary-overlay) + ;; Obtain the dragged text in region. When the loop was + ;; skipped, value-selection remains nil. + (unless value-selection (setq value-selection (buffer-substring start end)) - (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) - (ignore-errors (deactivate-mark) ; care existing region in other window - (mouse-set-point event) - (tooltip-show value-selection))) - (tooltip-hide)) - ;; Do not modify buffer under mouse when "event was click", - ;; "drag negligible", or - ;; "drag to read-only". - (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" - (member 'secondary-selection ; "drag negligible" - (mapcar (lambda (xxx) (overlay-get xxx 'face)) - (overlays-at (posn-point (event-end event))))) - buffer-read-only) - ;; Do not modify buffer under mouse. - (cond - ;; "drag negligible" or "drag to read-only", restore region. - (value-selection - (select-window window) ; In case miss drag to other window - (goto-char point) + + ;; Check if selected text is read-only. + (dolist (index (number-sequence start end)) + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq text-from-read-only (or text-from-read-only + (get-text-property index 'read-only))))) + (ignore-errors + (setq window-to-paste (posn-window (event-end event))) + (setq point-to-paste (posn-point (event-end event))) + + ;; Check if point under mouse is read-only. + (save-window-excursion + (select-window window-to-paste) + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq point-to-paste-read-only + (or buffer-read-only + (get-text-property point-to-paste 'read-only)))) + + ;; Check if "drag but negligible". Operation "drag but + ;; negligible" is defined as drag-and-drop the text to + ;; the original region. When modifier is pressed, the + ;; text will be inserted to inside of the original + ;; region. + (setq drag-but-negligible + (member mouse-drag-and-drop-region-face + (mapcar (lambda (xxx) (overlay-get xxx 'face)) + (overlays-at point-to-paste)))) + + ;; Show tooltip. + (when mouse-drag-and-drop-region-show-tooltip + (overlay-put mouse-drag-and-drop-overlay + 'face mouse-drag-and-drop-region-face) + (deactivate-mark) ; Maintain region in other window. + (mouse-set-point event) + (setq cursor-type (if (or point-to-paste-read-only + drag-but-negligible) + 'hollow + 'bar)) + (if (and (not drag-but-negligible) + (not point-to-paste-read-only)) + (tooltip-show value-selection) + (tooltip-hide))))) + ;; Hide a tooltip. + (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide))) + + + ;; Check if modifier was pressed on drop. + (setq no-modifier-on-drop + (not (member mouse-drag-and-drop-region (event-modifiers event)))) + + ;; Check if event was "click". + ;; (setq clicked (equal (mouse-posn-property (event-end event) 'face) 'region)) + (setq clicked (not value-selection)) + + ;; Do not modify any buffers when event is "click", + ;; "drag but negligible", or "drag to read-only". + (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ + (if no-modifier-on-drop + mouse-drag-and-drop-region-cut-when-buffers-differ + (not mouse-drag-and-drop-region-cut-when-buffers-differ))) + (wanna-paste-to-same-buffer (equal (window-buffer window-to-paste) buffer)) + (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer + no-modifier-on-drop)) + (wanna-cut-on-other-buffer (and (not wanna-paste-to-same-buffer) + mouse-drag-and-drop-region-cut-when-buffers-differ)) + (cannot-paste (or point-to-paste-read-only + (when (or wanna-cut-on-same-buffer + wanna-cut-on-other-buffer) + text-from-read-only)))) + + (cond + ;; Move point within region. + (clicked + (deactivate-mark) + (mouse-set-point event)) + ;; Undo operation. Set back the original text as region. + ((or (and drag-but-negligible + no-modifier-on-drop) + cannot-paste) + ;; Inform user either source or destination buffer cannot be modified. + (when (and (not drag-but-negligible) + cannot-paste) + (message "Buffer is read-only")) + + ;; Select source window back and restore region. + ;; (set-window-point window point) + (select-window window) + (goto-char point) + (setq deactivate-mark nil) + (activate-mark)) + ;; Modify buffers. + (t + ;; * DESTINATION BUFFER:: + ;; Insert the text to destination buffer under mouse. + (select-window window-to-paste) + (goto-char point-to-paste) + (push-mark) + (insert value-selection) + ;; On success, set the text as region on destination buffer. + (when (not (equal (mark) (point))) (setq deactivate-mark nil) (activate-mark)) - ;; "event was click" - (t - (deactivate-mark) - (mouse-set-point event))) - ;; Modify buffer under mouse by inserting text. - (push-mark) - (insert value-selection) - (when (not (equal (mark) (point))) ; on success insert - (setq deactivate-mark nil) - (activate-mark)) ; have region on destination - ;; Take care of initial region on source. - (if (equal (current-buffer) buffer) ; when same buffer - (let (deactivate-mark) ; remove text - (unless (member mouse-drag-and-drop-region (event-modifiers event)) - (kill-region (overlay-start mouse-secondary-overlay) - (overlay-end mouse-secondary-overlay)))) - (let ((window1 (selected-window))) ; when beyond buffer - (select-window window) - (goto-char point) ; restore point on source window - (activate-mark) ; restore region - (select-window window1)))) - (delete-overlay mouse-secondary-overlay))) + + ;; * SOURCE BUFFER:: + ;; Set back the original text as region or delete the original + ;; text, on source buffer. + (if wanna-paste-to-same-buffer + ;; When source buffer and destination buffer are the same, + ;; remove the original text. + (when no-modifier-on-drop + (let (deactivate-mark) + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)))) + ;; When source buffer and destination buffer are different, + ;; keep (set back the original text as region) or remove the + ;; original text. + (select-window window) ; Select window with source buffer. + (goto-char point) ; Move point to the original text on source buffer. + + (if mouse-drag-and-drop-region-cut-when-buffers-differ + ;; Remove the dragged text from source buffer like + ;; operation `cut'. + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)) + ;; Set back the dragged text as region on source buffer + ;; like operation `copy'. + (activate-mark)) + (select-window window-to-paste))))) + + ;; Clean up. + (delete-overlay mouse-drag-and-drop-overlay))) \f ;;; Bindings for mouse commands. ^ permalink raw reply related [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-27 13:11 ` mouse-drag-and-drop-region Tak Kunihiro @ 2017-11-28 8:50 ` martin rudalics 2017-12-01 14:16 ` mouse-drag-and-drop-region Tak Kunihiro 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-11-28 8:50 UTC (permalink / raw) To: Tak Kunihiro; +Cc: eliz, tak.kunihiro, agrambot, emacs-devel > I re-revised mouse-drag-and-drop-region. I'm sending replay to > https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00589.html, > ChangeLog, and patch. Thanks. Kindly send patches always as attachments, this one choked here because of a missing form feed near the end. > I got rid of usage of secondary-overlay. I > define a new variable mouse-drag-and-drop-region-face. Very good. >>> How to show insert point? >> >> I think that by default the insert point should be shown by the >> mouse cursor alone. Optionally, I see no problem showing the normal >> cursor just as `mouse-drag-region' does, maybe with some >> customizable cursor type (I think "bar" would give a better feeling >> than "box"). > > OK. Only set point by mouse-set-point when > mouse-drag-and-drop-region-show-tooltip is non-nil with changing > cursor type. I also changed the default of > mouse-drag-and-drop-region-show-tooltip to nil to be more stable > against accident during dragging. This reverts too much from your initial proposal. Basically, all your initial ideas are fine, just that if on one or the other system they don't work as intended or some user finds them annoying, there should be options to turn them off. And, if accidents happen during dragging with any of the options non-nil, we should try to handle or fix them anyway. So I would use three options instead of one: `mouse-drag-and-drop-region-show-tooltip' to toggle the showing of tooltips during dragging and nothing else. `mouse-drag-and-drop-region-highlight-region' to toggle highlighting the region with `mouse-drag-and-drop-region-face' (which gives the user the feedback whether cutting may fail when dropping into the region itself, which was your initial intention IIUC). `mouse-drag-and-drop-region-show-cursor' which should synchronize the cursor with the mouse cursor just as `mouse-drag-track' does. This is the only option I personally would default to nil but if you or others like it on by default I certainly won't insist. >> More precisely, you should wrap 'track-mouse' and whatever you do >> after it terminates in a 'condition-case' form and in the error part >> restore everything to the saved values. Like so: >> >> (... ; save the state here >> (condition-case nil >> (progn >> (track-mouse >> ) >> ) >> (error ... ; restore the state here >> ))) >> >> If you have any problems coding that, please ask. > > Even track-mouse is sandwiched by condition-case, I cannot catch a > error typing during dragging. When I try to drop the region on the toolbar or another frame (things some users might try out soon because they are not too far-fetched) I currently get something like Wrong type argument: windowp, #<frame emacs@MACHNO 05408d00> Before your last patch this was a complaint about an overlay. In either case, users who don't know much about the internals of Emacs will wonder what these messages are about and where they come from. We should tell them instead something like "Drop failed" or "Cannot drop into initial region". And, if such an error occurs, we should be sure to delete the `mouse-drag-and-drop-overlay' and restore the initial region, if necessary. > However, as inferred already, when > mouse-drag-and-drop-region-show-tooltip is nil, it is more stable even > typing key during dragging. Yes. But typing during dragging should be caught by us in some way. It should not defer us from showing tooltips by default. One final remark: Stepping through every single character in ;; Check if selected text is read-only. (dolist (index (number-sequence start end)) ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) (setq text-from-read-only (or text-from-read-only (get-text-property index 'read-only))))) is not very efficient if the region is large. Please consider using `next-single-char-property-change' instead. Thanks again, martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-11-28 8:50 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-01 14:16 ` Tak Kunihiro 2017-12-02 10:16 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Tak Kunihiro @ 2017-12-01 14:16 UTC (permalink / raw) To: rudalics; +Cc: eliz, tak.kunihiro, agrambot, emacs-devel I re-re-revised mouse-drag-and-drop-region. I'm sending replay to https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00663.html, ChangeLog, and patch. * ChangeLog 2017-12-01 Tak Kunihiro <tkk@misasa.okayama-u.ac.jp> Improve comments and have four new options * lisp/mouse.el (mouse-drag-and-drop-region): Have option to make dragging cut among buffers. Make usage of tooltip option. (mouse-drag-and-drop-region-cut-when-buffers-differ): New variable. If non-nil, text is cut instead of copied when dragged among buffers. (mouse-drag-and-drop-region-show-tooltip): New variable. If non-nil, text is shown by tooltip in a graphic display. (mouse-drag-and-drop-region-show-cursor): New variable. If non-nil, point is set to where the mouse cursor. (mouse-drag-and-drop-region-face): New variable for face. The face is used to highlight the original text. * Replay > `mouse-drag-and-drop-region-show-tooltip' to toggle the showing of > tooltips during dragging and nothing else. OK. > `mouse-drag-and-drop-region-highlight-region' to toggle highlighting > the region with `mouse-drag-and-drop-region-face' > > `mouse-drag-and-drop-region-show-cursor' which should synchronize the > cursor with the mouse cursor just as `mouse-drag-track' does. OK. A new variable `mouse-drag-and-drop-region-show-cursor' is defined. When mouse-drag-and-drop-region-show-cursor is non-nil, the region also is highlighted. I did not define a variable `mouse-drag-and-drop-region-highlight-region'. Also, cursor-type would be changed to give user feedback. > When I try to drop the region on the toolbar or another frame (things > some users might try out soon because they are not too far-fetched) I > currently get something like > > Wrong type argument: windowp, #<frame emacs@MACHNO 05408d00> > > We should tell them instead something like "Drop failed" or "Cannot > drop into initial region". And, if such an error occurs, we should be > sure to delete the `mouse-drag-and-drop-overlay' and restore the > initial region, if necessary. Now the code checks if cursor is on the text area. If not, it restore the initial region. I'm not sure to tell "Drop failed" is a good idea. When an user wants to undo the drag, he may drag to toolbar. Restore the initial region is what is expected. The code for now does not tell the message. > But typing during dragging should be caught by us in some way. It > should not defer us from showing tooltips by default. I tried read-key instead of read-event as suggested by Alex and that solved the problem. > Stepping through every single character in > > (dolist (index (number-sequence start end)) > ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) > (setq text-from-read-only (or text-from-read-only > (get-text-property index 'read-only))))) > > is not very efficient if the region is large. Please consider using > `next-single-char-property-change' instead. OK. * Patch diff --git a/lisp/mouse.el b/lisp/mouse.el old mode 100644 new mode 100755 index 17d1732..3e59f6f --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -2361,6 +2361,31 @@ text is copied instead of being cut." :version "26.1" :group 'mouse) +(defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil + "If non-nil, cut text also when source and destination buffers differ. +If this option is nil, `mouse-drag-and-drop-region' will leave +the text in the source buffer alone when dropping it in a +different buffer. If this is non-nil, it will cut the text just +as it does when dropping text in the source buffer." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-tooltip t + "If non-nil, text is shown by a tooltip in a graphic display." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defvar mouse-drag-and-drop-region-show-cursor t + "If non-nil, point is set to where the mouse cursor is during +dragging and the original text is highlighted by face +`mouse-drag-and-drop-region-face'.") + +(defvar mouse-drag-and-drop-region-face 'region + "Face to highlight the original text during dragging. +See also `mouse-drag-and-drop-region-show-cursor'.") + (defun mouse-drag-and-drop-region (event) "Move text in the region to point where mouse is dragged to. The transportation of text is also referred as `drag and drop'. @@ -2369,66 +2394,197 @@ modifier key was pressed when dropping, and the value of the variable `mouse-drag-and-drop-region' is that modifier, the text is copied instead of being cut." (interactive "e") - (require 'tooltip) - (let ((start (region-beginning)) - (end (region-end)) - (point (point)) - (buffer (current-buffer)) - (window (selected-window)) - value-selection) + (let* ((mouse-button (event-basic-type last-input-event)) + (mouse-drag-and-drop-region-show-tooltip + (and mouse-drag-and-drop-region-show-tooltip + (display-multi-frame-p) + (require 'tooltip))) + (start (region-beginning)) + (end (region-end)) + (point (point)) + (buffer (current-buffer)) + (window (selected-window)) + (cursor-type cursor-type) + (text-from-read-only buffer-read-only) + (mouse-drag-and-drop-overlay (make-overlay start end)) + point-to-paste + point-to-paste-read-only + window-to-paste + buffer-to-paste + cursor-in-text-area + no-modifier-on-drop + drag-but-negligible + clicked + value-selection) ; This remains nil when event was "click". + (track-mouse - ;; When event was click instead of drag, skip loop + ;; When event was "click" instead of "drag", skip loop. (while (progn - (setq event (read-event)) + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00364.html + (setq event (read-key)) ; read-event or read-key (or (mouse-movement-p event) ;; Handle `mouse-autoselect-window'. (eq (car-safe event) 'select-window))) - (unless value-selection ; initialization - (delete-overlay mouse-secondary-overlay) + ;; Obtain the dragged text in region. When the loop was + ;; skipped, value-selection remains nil. + (unless value-selection (setq value-selection (buffer-substring start end)) - (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) - (ignore-errors (deactivate-mark) ; care existing region in other window - (mouse-set-point event) - (tooltip-show value-selection))) - (tooltip-hide)) - ;; Do not modify buffer under mouse when "event was click", - ;; "drag negligible", or - ;; "drag to read-only". - (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" - (member 'secondary-selection ; "drag negligible" - (mapcar (lambda (xxx) (overlay-get xxx 'face)) - (overlays-at (posn-point (event-end event))))) - buffer-read-only) - ;; Do not modify buffer under mouse. - (cond - ;; "drag negligible" or "drag to read-only", restore region. - (value-selection - (select-window window) ; In case miss drag to other window - (goto-char point) + + ;; Check if selected text is read-only. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00663.html + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq text-from-read-only (or text-from-read-only + (get-text-property start 'read-only) + (not (equal + (next-single-char-property-change start 'read-only nil end) + end))))) + (ignore-errors + (setq window-to-paste (posn-window (event-end event))) + (setq point-to-paste (posn-point (event-end event))) + (setq buffer-to-paste (and (windowp window-to-paste) + (window-buffer window-to-paste))) + (setq cursor-in-text-area (and window-to-paste + point-to-paste + buffer-to-paste)) + + (when cursor-in-text-area + ;; Check if point under mouse is read-only. + (save-window-excursion + (select-window window-to-paste) + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq point-to-paste-read-only + (or buffer-read-only + (get-text-property point-to-paste 'read-only)))) + + ;; Check if "drag but negligible". Operation "drag but + ;; negligible" is defined as drag-and-drop the text to + ;; the original region. When modifier is pressed, the + ;; text will be inserted to inside of the original + ;; region. + (setq drag-but-negligible + (member mouse-drag-and-drop-region-face + (mapcar (lambda (xxx) (overlay-get xxx 'face)) + (overlays-at point-to-paste))))) + + ;; Show a tooltip. + (if (and mouse-drag-and-drop-region-show-tooltip + (not drag-but-negligible) + (not point-to-paste-read-only) + cursor-in-text-area) + (tooltip-show value-selection) + (tooltip-hide)) + + ;; Show cursor and highlight the original region. + (when mouse-drag-and-drop-region-show-cursor + ;; Modify cursor even when point is out of frame. + (setq cursor-type (cond + ((not cursor-in-text-area) + nil) + ((or point-to-paste-read-only + drag-but-negligible) + 'hollow) + (t + 'bar))) + (when cursor-in-text-area + (overlay-put mouse-drag-and-drop-overlay + 'face mouse-drag-and-drop-region-face) + (deactivate-mark) ; Maintain region in other window. + (mouse-set-point event))))) + + ;; Hide a tooltip. + (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide))) + + ;; Check if modifier was pressed on drop. + (setq no-modifier-on-drop + (not (member mouse-drag-and-drop-region (event-modifiers event)))) + + ;; Check if event was "click". + (setq clicked (not value-selection)) + + ;; Restore status on drag to outside of text-area or non-mouse input. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00486.html + (when (or (not cursor-in-text-area) + (not (equal (event-basic-type event) mouse-button))) + (setq drag-but-negligible t + no-modifier-on-drop t)) + + ;; Do not modify any buffers when event is "click", + ;; "drag but negligible", or "drag to read-only". + (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ + (if no-modifier-on-drop + mouse-drag-and-drop-region-cut-when-buffers-differ + (not mouse-drag-and-drop-region-cut-when-buffers-differ))) + (wanna-paste-to-same-buffer (equal buffer-to-paste buffer)) + (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer + no-modifier-on-drop)) + (wanna-cut-on-other-buffer (and (not wanna-paste-to-same-buffer) + mouse-drag-and-drop-region-cut-when-buffers-differ)) + (cannot-paste (or point-to-paste-read-only + (when (or wanna-cut-on-same-buffer + wanna-cut-on-other-buffer) + text-from-read-only)))) + + (cond + ;; Move point within region. + (clicked + (deactivate-mark) + (mouse-set-point event)) + ;; Undo operation. Set back the original text as region. + ((or (and drag-but-negligible + no-modifier-on-drop) + cannot-paste) + ;; Inform user either source or destination buffer cannot be modified. + (when (and (not drag-but-negligible) + cannot-paste) + (message "Buffer is read-only")) + + ;; Select source window back and restore region. + ;; (set-window-point window point) + (select-window window) + (goto-char point) + (setq deactivate-mark nil) + (activate-mark)) + ;; Modify buffers. + (t + ;; * DESTINATION BUFFER:: + ;; Insert the text to destination buffer under mouse. + (select-window window-to-paste) + (goto-char point-to-paste) + (push-mark) + (insert value-selection) + ;; On success, set the text as region on destination buffer. + (when (not (equal (mark) (point))) (setq deactivate-mark nil) (activate-mark)) - ;; "event was click" - (t - (deactivate-mark) - (mouse-set-point event))) - ;; Modify buffer under mouse by inserting text. - (push-mark) - (insert value-selection) - (when (not (equal (mark) (point))) ; on success insert - (setq deactivate-mark nil) - (activate-mark)) ; have region on destination - ;; Take care of initial region on source. - (if (equal (current-buffer) buffer) ; when same buffer - (let (deactivate-mark) ; remove text - (unless (member mouse-drag-and-drop-region (event-modifiers event)) - (kill-region (overlay-start mouse-secondary-overlay) - (overlay-end mouse-secondary-overlay)))) - (let ((window1 (selected-window))) ; when beyond buffer - (select-window window) - (goto-char point) ; restore point on source window - (activate-mark) ; restore region - (select-window window1)))) - (delete-overlay mouse-secondary-overlay))) + + ;; * SOURCE BUFFER:: + ;; Set back the original text as region or delete the original + ;; text, on source buffer. + (if wanna-paste-to-same-buffer + ;; When source buffer and destination buffer are the same, + ;; remove the original text. + (when no-modifier-on-drop + (let (deactivate-mark) + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)))) + ;; When source buffer and destination buffer are different, + ;; keep (set back the original text as region) or remove the + ;; original text. + (select-window window) ; Select window with source buffer. + (goto-char point) ; Move point to the original text on source buffer. + + (if mouse-drag-and-drop-region-cut-when-buffers-differ + ;; Remove the dragged text from source buffer like + ;; operation `cut'. + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)) + ;; Set back the dragged text as region on source buffer + ;; like operation `copy'. + (activate-mark)) + (select-window window-to-paste))))) + + ;; Clean up. + (delete-overlay mouse-drag-and-drop-overlay))) \f ;;; Bindings for mouse commands. ^ permalink raw reply related [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-01 14:16 ` mouse-drag-and-drop-region Tak Kunihiro @ 2017-12-02 10:16 ` martin rudalics 2017-12-03 10:06 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-12-02 10:16 UTC (permalink / raw) To: Tak Kunihiro; +Cc: eliz, tak.kunihiro, agrambot, emacs-devel > I re-re-revised mouse-drag-and-drop-region. I'm sending replay to > https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00663.html, > ChangeLog, and patch. Thank you. Still, please consider sending patches as attachments so applying them is simpler. > OK. A new variable `mouse-drag-and-drop-region-show-cursor' is > defined. Please note that the first line of a doc string may contain complete sentences only. You could write something like (defvar mouse-drag-and-drop-region-show-cursor t "If non-nil, move point with mouse cursor during dragging. In addition, highlight the original region with `mouse-drag-and-drop-region-face'.") > Now the code checks if cursor is on the text area. If not, it restore > the initial region. I'm not sure to tell "Drop failed" is a good > idea. When an user wants to undo the drag, he may drag to toolbar. > Restore the initial region is what is expected. The code for now does > not tell the message. OK. But the code fails to poperly restore the previous cursor type when the drop fails. For example when with emacs -Q I evaluate (progn (setq mouse-drag-and-drop-region t) (setq mouse-drag-and-drop-region-show-cursor t) (display-buffer "*Messages*")) mark some text in the *scratch* buffer and accidentally drag-and-drop it on the mode line of the *Messages* buffer, the cursor in the *Messages* buffer disappears. I think you have to remember the old cursor type and make sure it gets restored whatever happens. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-02 10:16 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-03 10:06 ` martin rudalics 2017-12-03 13:36 ` mouse-drag-and-drop-region martin rudalics 2017-12-05 4:57 ` mouse-drag-and-drop-region Tak Kunihiro 0 siblings, 2 replies; 89+ messages in thread From: martin rudalics @ 2017-12-03 10:06 UTC (permalink / raw) To: Tak Kunihiro; +Cc: eliz, tak.kunihiro, agrambot, emacs-devel [-- Attachment #1: Type: text/plain, Size: 2558 bytes --] I have found some time to look into this again and encountered a few additional problems. One is that when a user has three windows - T at the top of a frame, M in the middle and B at the bottom of the frame - and wants to drag a region from T to B. In this case the position of M's point will inevitably change although the user probably had no intentions to do that. So we should make sure to restore the point of any window that might be affected by the drag. Another one is that when a user has set `scroll-margin' to some non-zero value, any window involved in the drag may scroll in order to move that window's point out of the scroll margin. This may affect unrelated windows (as in the TMB example above) but also the window where the drag started. We could use the trick of `mouse-drag-track' to bind `scroll-margin' to zero but this might not work if a user has made this variable buffer-local (note that `mouse-drag-track' never leaves the current buffer so it has no such problem). So I think that we should remember for each window on the involved frame its start and point positions and restore them unless the window is the one where the drop happened. I attached a patch for this which also restores the cursor type of every window. The patch includes all your latest changes (so it should apply against the repository version) and is largely untested but should give you the idea what to do. Please consider also the following four bindings in `mouse-drag-track': (echo-keystrokes 0) (make-cursor-line-fully-visible nil) ;; Suppress automatic hscrolling, because that is a nuisance ;; when setting point near the right fringe (but see below). (auto-hscroll-mode-saved auto-hscroll-mode) (old-track-mouse track-mouse) Maybe they are useful for you as well (a lot of experience went into the coding of that function). Also please consider to restrict the size of the tooltip shown (think of someone who wants to drag the entire text of a buffer). I think `mouse-drag-and-drop-region-show-tooltip' should optionally allow to specify a number giving the maximum length of the string which I would divide into one half for the beginning of the text, one half for the end and ellipses in between. Finally, please think of how to embed your function into other packages: For example, how would a user drag file names from one dired buffer to another in order to copy or move the associated files from one directory to another? Can we accomodate an exit function to do the pasting job? Thanks, martin [-- Attachment #2: mouse.el.diff --] [-- Type: text/plain, Size: 15560 bytes --] diff --git a/lisp/mouse.el b/lisp/mouse.el index 17d1732..02ba364 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -2361,6 +2361,31 @@ mouse-drag-and-drop-region :version "26.1" :group 'mouse) +(defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil + "If non-nil, cut text also when source and destination buffers differ. +If this option is nil, `mouse-drag-and-drop-region' will leave +the text in the source buffer alone when dropping it in a +different buffer. If this is non-nil, it will cut the text just +as it does when dropping text in the source buffer." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-tooltip t + "If non-nil, text is shown by a tooltip in a graphic display." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defvar mouse-drag-and-drop-region-show-cursor t + "If non-nil, point is set to where the mouse cursor is during +dragging and the original text is highlighted by face +`mouse-drag-and-drop-region-face'.") + +(defvar mouse-drag-and-drop-region-face 'region + "Face to highlight the original text during dragging. +See also `mouse-drag-and-drop-region-show-cursor'.") + (defun mouse-drag-and-drop-region (event) "Move text in the region to point where mouse is dragged to. The transportation of text is also referred as `drag and drop'. @@ -2369,66 +2394,233 @@ mouse-drag-and-drop-region variable `mouse-drag-and-drop-region' is that modifier, the text is copied instead of being cut." (interactive "e") - (require 'tooltip) - (let ((start (region-beginning)) - (end (region-end)) - (point (point)) - (buffer (current-buffer)) - (window (selected-window)) - value-selection) - (track-mouse - ;; When event was click instead of drag, skip loop - (while (progn - (setq event (read-event)) - (or (mouse-movement-p event) - ;; Handle `mouse-autoselect-window'. - (eq (car-safe event) 'select-window))) - (unless value-selection ; initialization - (delete-overlay mouse-secondary-overlay) - (setq value-selection (buffer-substring start end)) - (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) - (ignore-errors (deactivate-mark) ; care existing region in other window - (mouse-set-point event) - (tooltip-show value-selection))) - (tooltip-hide)) - ;; Do not modify buffer under mouse when "event was click", - ;; "drag negligible", or - ;; "drag to read-only". - (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" - (member 'secondary-selection ; "drag negligible" - (mapcar (lambda (xxx) (overlay-get xxx 'face)) - (overlays-at (posn-point (event-end event))))) - buffer-read-only) - ;; Do not modify buffer under mouse. - (cond - ;; "drag negligible" or "drag to read-only", restore region. - (value-selection - (select-window window) ; In case miss drag to other window - (goto-char point) - (setq deactivate-mark nil) - (activate-mark)) - ;; "event was click" - (t - (deactivate-mark) - (mouse-set-point event))) - ;; Modify buffer under mouse by inserting text. - (push-mark) - (insert value-selection) - (when (not (equal (mark) (point))) ; on success insert - (setq deactivate-mark nil) - (activate-mark)) ; have region on destination - ;; Take care of initial region on source. - (if (equal (current-buffer) buffer) ; when same buffer - (let (deactivate-mark) ; remove text - (unless (member mouse-drag-and-drop-region (event-modifiers event)) - (kill-region (overlay-start mouse-secondary-overlay) - (overlay-end mouse-secondary-overlay)))) - (let ((window1 (selected-window))) ; when beyond buffer - (select-window window) - (goto-char point) ; restore point on source window - (activate-mark) ; restore region - (select-window window1)))) - (delete-overlay mouse-secondary-overlay))) + (let* ((mouse-button (event-basic-type last-input-event)) + (mouse-drag-and-drop-region-show-tooltip + (and mouse-drag-and-drop-region-show-tooltip + (display-multi-frame-p) + (require 'tooltip))) + (start (region-beginning)) + (end (region-end)) + (point (point)) + (buffer (current-buffer)) + (window (selected-window)) + (text-from-read-only buffer-read-only) + (mouse-drag-and-drop-overlay (make-overlay start end)) + point-to-paste + point-to-paste-read-only + window-to-paste + buffer-to-paste + cursor-in-text-area + no-modifier-on-drop + drag-but-negligible + clicked + value-selection ; This remains nil when event was "click". + states + window-dropped) + + ;; STATES stores for each window on this frame its start and point + ;; positions so we can restore them on all windows but for the one + ;; where the drop occurs. For inter-frame drags we'll have to do + ;; this for all windows on all visible frames. In addition we save + ;; also the cursor type for the window's buffer so we can restore it + ;; in case we modified it. + (walk-window-tree + (lambda (window) + (setq states + (cons + (list + window + (copy-marker (window-start window)) + (copy-marker (window-point window)) + (with-current-buffer (window-buffer window) + cursor-type)) + states)))) + + (condition-case nil + (progn + (track-mouse + ;; When event was "click" instead of "drag", skip loop. + (while (progn + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00364.html + (setq event (read-key)) ; read-event or read-key + (or (mouse-movement-p event) + ;; Handle `mouse-autoselect-window'. + (eq (car-safe event) 'select-window))) + ;; Obtain the dragged text in region. When the loop was + ;; skipped, value-selection remains nil. + (unless value-selection + (setq value-selection (buffer-substring start end)) + + ;; Check if selected text is read-only. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00663.html + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq text-from-read-only (or text-from-read-only + (get-text-property start 'read-only) + (not (equal + (next-single-char-property-change start 'read-only nil end) + end))))) + (setq window-to-paste (posn-window (event-end event))) + (setq point-to-paste (posn-point (event-end event))) + (setq buffer-to-paste (and (windowp window-to-paste) + (window-buffer window-to-paste))) + (setq cursor-in-text-area (and window-to-paste + point-to-paste + buffer-to-paste)) + + (when cursor-in-text-area + ;; Check if point under mouse is read-only. + (save-window-excursion + (select-window window-to-paste) + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq point-to-paste-read-only + (or buffer-read-only + (get-text-property point-to-paste 'read-only)))) + + ;; Check if "drag but negligible". Operation "drag but + ;; negligible" is defined as drag-and-drop the text to + ;; the original region. When modifier is pressed, the + ;; text will be inserted to inside of the original + ;; region. + (setq drag-but-negligible + (member mouse-drag-and-drop-region-face + (mapcar (lambda (xxx) (overlay-get xxx 'face)) + (overlays-at point-to-paste))))) + + ;; Show a tooltip. + (if (and mouse-drag-and-drop-region-show-tooltip + (not drag-but-negligible) + (not point-to-paste-read-only) + cursor-in-text-area) + (tooltip-show value-selection) + (tooltip-hide)) + + ;; Show cursor and highlight the original region. + (when mouse-drag-and-drop-region-show-cursor + ;; Modify cursor even when point is out of frame. + (setq cursor-type (cond + ((not cursor-in-text-area) + nil) + ((or point-to-paste-read-only + drag-but-negligible) + 'hollow) + (t + 'bar))) + (when cursor-in-text-area + (overlay-put mouse-drag-and-drop-overlay + 'face mouse-drag-and-drop-region-face) + (deactivate-mark) ; Maintain region in other window. + (mouse-set-point event))))) + + ;; Hide a tooltip. + (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide)) + + ;; Check if modifier was pressed on drop. + (setq no-modifier-on-drop + (not (member mouse-drag-and-drop-region (event-modifiers event)))) + + ;; Check if event was "click". + (setq clicked (not value-selection)) + + ;; Restore status on drag to outside of text-area or non-mouse input. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00486.html + (when (or (not cursor-in-text-area) + (not (equal (event-basic-type event) mouse-button))) + (setq drag-but-negligible t + no-modifier-on-drop t)) + + ;; Do not modify any buffers when event is "click", + ;; "drag but negligible", or "drag to read-only". + (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ + (if no-modifier-on-drop + mouse-drag-and-drop-region-cut-when-buffers-differ + (not mouse-drag-and-drop-region-cut-when-buffers-differ))) + (wanna-paste-to-same-buffer (equal buffer-to-paste buffer)) + (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer + no-modifier-on-drop)) + (wanna-cut-on-other-buffer (and (not wanna-paste-to-same-buffer) + mouse-drag-and-drop-region-cut-when-buffers-differ)) + (cannot-paste (or point-to-paste-read-only + (when (or wanna-cut-on-same-buffer + wanna-cut-on-other-buffer) + text-from-read-only)))) + + (cond + ;; Move point within region. + (clicked + (deactivate-mark) + (mouse-set-point event)) + ;; Undo operation. Set back the original text as region. + ((or (and drag-but-negligible + no-modifier-on-drop) + cannot-paste) + ;; Inform user either source or destination buffer cannot be modified. + (when (and (not drag-but-negligible) + cannot-paste) + (message "Buffer is read-only")) + + ;; Select source window back and restore region. + ;; (set-window-point window point) + (select-window window) + (goto-char point) + (setq deactivate-mark nil) + (activate-mark)) + ;; Modify buffers. + (t + ;; * DESTINATION BUFFER:: + ;; Insert the text to destination buffer under mouse. + (select-window window-to-paste) + (setq window-dropped window-to-paste) + (goto-char point-to-paste) + (push-mark) + (insert value-selection) + ;; On success, set the text as region on destination buffer. + (when (not (equal (mark) (point))) + (setq deactivate-mark nil) + (activate-mark)) + + ;; * SOURCE BUFFER:: + ;; Set back the original text as region or delete the original + ;; text, on source buffer. + (if wanna-paste-to-same-buffer + ;; When source buffer and destination buffer are the same, + ;; remove the original text. + (when no-modifier-on-drop + (let (deactivate-mark) + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)))) + ;; When source buffer and destination buffer are different, + ;; keep (set back the original text as region) or remove the + ;; original text. + (select-window window) ; Select window with source buffer. + (goto-char point) ; Move point to the original text on source buffer. + + (if mouse-drag-and-drop-region-cut-when-buffers-differ + ;; Remove the dragged text from source buffer like + ;; operation `cut'. + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)) + ;; Set back the dragged text as region on source buffer + ;; like operation `copy'. + (activate-mark)) + (select-window window-to-paste)))))) + (error nil)) + + ;; Clean up. + (delete-overlay mouse-drag-and-drop-overlay) + + ;; Restore old states but for the window where the drop + ;; occurred. Restore cursor types for all windows. + (dolist (state states) + (let ((window (car state))) + (unless (eq window window-dropped) + (set-window-start window (nth 1 state) 'noforce) + (set-marker (nth 1 state) nil) + ;; If window is selected, the following automatically sets + ;; point for that window's buffer. + (set-window-point window (nth 2 state)) + (set-marker (nth 2 state) nil)) + (with-current-buffer (window-buffer window) + (setq cursor-type (nth 3 state))))))) \f ;;; Bindings for mouse commands. ^ permalink raw reply related [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-03 10:06 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-03 13:36 ` martin rudalics 2017-12-05 4:57 ` mouse-drag-and-drop-region Tak Kunihiro 1 sibling, 0 replies; 89+ messages in thread From: martin rudalics @ 2017-12-03 13:36 UTC (permalink / raw) To: Tak Kunihiro; +Cc: eliz, tak.kunihiro, agrambot, emacs-devel > We could use the trick of `mouse-drag-track' to bind `scroll-margin' to > zero but this might not work if a user has made this variable > buffer-local (note that `mouse-drag-track' never leaves the current > buffer so it has no such problem). Ignore this: Binding `scroll-margin' to zero obviously overrides any buffer-local setting as well. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-03 10:06 ` mouse-drag-and-drop-region martin rudalics 2017-12-03 13:36 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-05 4:57 ` Tak Kunihiro 2017-12-05 8:53 ` mouse-drag-and-drop-region martin rudalics 1 sibling, 1 reply; 89+ messages in thread From: Tak Kunihiro @ 2017-12-05 4:57 UTC (permalink / raw) To: rudalics; +Cc: eliz, tak.kunihiro, agrambot, emacs-devel [-- Attachment #1: Type: Text/Plain, Size: 2122 bytes --] > So I think that we should remember for each window on the involved frame > its start and point positions and restore them unless the window is the > one where the drop happened. I attached a patch for this which also > restores the cursor type of every window. The patch includes all your > latest changes (so it should apply against the repository version) and > is largely untested but should give you the idea what to do. Thank you. I think that by your revision, the problem was solved. I also revised code not to let user drop the text to minibuffer. This time, I attach a patch as a separated file. > Please consider also the following four bindings in `mouse-drag-track': > > (echo-keystrokes 0) > > (make-cursor-line-fully-visible nil) > > ;; Suppress automatic hscrolling, because that is a nuisance > ;; when setting point near the right fringe (but see below). > (auto-hscroll-mode-saved auto-hscroll-mode) > > (old-track-mouse track-mouse) > > Maybe they are useful for you as well (a lot of experience went into the > coding of that function). I wonder if this is beyond my skill. Could you revise this part? > Also please consider to restrict the size of the tooltip shown (think of > someone who wants to drag the entire text of a buffer). I think > `mouse-drag-and-drop-region-show-tooltip' should optionally allow to > specify a number giving the maximum length of the string which I would > divide into one half for the beginning of the text, one half for the end > and ellipses in between. It is a good idea. Now tooltip shows only substring. I think mouse-drag-and-drop-region-show-tooltip should be something like 256 by default. > Finally, please think of how to embed your function into other packages: > For example, how would a user drag file names from one dired buffer to > another in order to copy or move the associated files from one directory > to another? Can we accomodate an exit function to do the pasting job? It is a good idea. I suppose you mean dragging `file' when event-start is with 'dired-filename. [-- Attachment #2: mouse.el.diff --] [-- Type: Text/X-Patch, Size: 16782 bytes --] diff --git a/lisp/mouse.el b/lisp/mouse.el index 17d1732..f1ca0ec --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -2361,6 +2361,33 @@ text is copied instead of being cut." :version "26.1" :group 'mouse) +(defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil + "If non-nil, cut text also when source and destination buffers differ. +If this option is nil, `mouse-drag-and-drop-region' will leave +the text in the source buffer alone when dropping it in a +different buffer. If this is non-nil, it will cut the text just +as it does when dropping text in the source buffer." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-tooltip 256 + "If non-nil, text is shown by a tooltip in a graphic display. +If this option is an integer, such as 32 or 64, a number giving +the maximum length of the string shown in tooltip." + :type 'integer + :version "26.1" + :group 'mouse) + +(defvar mouse-drag-and-drop-region-show-cursor t + "If non-nil, move point with mouse cursor during dragging. +In addition, highlight the original region with +`mouse-drag-and-drop-region-face'.") + +(defvar mouse-drag-and-drop-region-face 'region + "Face to highlight the original text during dragging. +See also `mouse-drag-and-drop-region-show-cursor'.") + (defun mouse-drag-and-drop-region (event) "Move text in the region to point where mouse is dragged to. The transportation of text is also referred as `drag and drop'. @@ -2369,66 +2396,248 @@ modifier key was pressed when dropping, and the value of the variable `mouse-drag-and-drop-region' is that modifier, the text is copied instead of being cut." (interactive "e") - (require 'tooltip) - (let ((start (region-beginning)) - (end (region-end)) - (point (point)) - (buffer (current-buffer)) - (window (selected-window)) - value-selection) - (track-mouse - ;; When event was click instead of drag, skip loop - (while (progn - (setq event (read-event)) - (or (mouse-movement-p event) - ;; Handle `mouse-autoselect-window'. - (eq (car-safe event) 'select-window))) - (unless value-selection ; initialization - (delete-overlay mouse-secondary-overlay) - (setq value-selection (buffer-substring start end)) - (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) - (ignore-errors (deactivate-mark) ; care existing region in other window - (mouse-set-point event) - (tooltip-show value-selection))) - (tooltip-hide)) - ;; Do not modify buffer under mouse when "event was click", - ;; "drag negligible", or - ;; "drag to read-only". - (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" - (member 'secondary-selection ; "drag negligible" - (mapcar (lambda (xxx) (overlay-get xxx 'face)) - (overlays-at (posn-point (event-end event))))) - buffer-read-only) - ;; Do not modify buffer under mouse. - (cond - ;; "drag negligible" or "drag to read-only", restore region. - (value-selection - (select-window window) ; In case miss drag to other window - (goto-char point) - (setq deactivate-mark nil) - (activate-mark)) - ;; "event was click" - (t - (deactivate-mark) - (mouse-set-point event))) - ;; Modify buffer under mouse by inserting text. - (push-mark) - (insert value-selection) - (when (not (equal (mark) (point))) ; on success insert - (setq deactivate-mark nil) - (activate-mark)) ; have region on destination - ;; Take care of initial region on source. - (if (equal (current-buffer) buffer) ; when same buffer - (let (deactivate-mark) ; remove text - (unless (member mouse-drag-and-drop-region (event-modifiers event)) - (kill-region (overlay-start mouse-secondary-overlay) - (overlay-end mouse-secondary-overlay)))) - (let ((window1 (selected-window))) ; when beyond buffer - (select-window window) - (goto-char point) ; restore point on source window - (activate-mark) ; restore region - (select-window window1)))) - (delete-overlay mouse-secondary-overlay))) + (let* ((mouse-button (event-basic-type last-input-event)) + (mouse-drag-and-drop-region-show-tooltip + (when (and mouse-drag-and-drop-region-show-tooltip + (display-multi-frame-p) + (require 'tooltip)) + mouse-drag-and-drop-region-show-tooltip)) + (start (region-beginning)) + (end (region-end)) + (point (point)) + (buffer (current-buffer)) + (window (selected-window)) + (text-from-read-only buffer-read-only) + (mouse-drag-and-drop-overlay (make-overlay start end)) + point-to-paste + point-to-paste-read-only + window-to-paste + buffer-to-paste + cursor-in-text-area + no-modifier-on-drop + drag-but-negligible + clicked + value-selection ; This remains nil when event was "click". + text-tooltip + states + window-dropped) + + ;; STATES stores for each window on this frame its start and point + ;; positions so we can restore them on all windows but for the one + ;; where the drop occurs. For inter-frame drags we'll have to do + ;; this for all windows on all visible frames. In addition we save + ;; also the cursor type for the window's buffer so we can restore it + ;; in case we modified it. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-12/msg00090.html + (walk-window-tree + (lambda (window) + (setq states + (cons + (list + window + (copy-marker (window-start window)) + (copy-marker (window-point window)) + (with-current-buffer (window-buffer window) + cursor-type)) + states)))) + + (condition-case nil + (progn + (track-mouse + ;; When event was "click" instead of "drag", skip loop. + (while (progn + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00364.html + (setq event (read-key)) ; read-event or read-key + (or (mouse-movement-p event) + ;; Handle `mouse-autoselect-window'. + (eq (car-safe event) 'select-window))) + ;; Obtain the dragged text in region. When the loop was + ;; skipped, value-selection remains nil. + (unless value-selection + (setq value-selection (buffer-substring start end)) + (when mouse-drag-and-drop-region-show-tooltip + (let ((text-size mouse-drag-and-drop-region-show-tooltip)) + (setq text-tooltip (if (and (integerp text-size) + (> (length value-selection) text-size)) + (concat + (substring value-selection 0 (/ text-size 2)) + "\n...\n" + (substring value-selection (- (/ text-size 2)) -1)) + value-selection)))) + + ;; Check if selected text is read-only. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00663.html + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq text-from-read-only (or text-from-read-only + (get-text-property start 'read-only) + (not (equal + (next-single-char-property-change start 'read-only nil end) + end))))) + (setq window-to-paste (posn-window (event-end event))) + (setq point-to-paste (posn-point (event-end event))) + (setq buffer-to-paste (let (buf) ; Set nil when target buffer is minibuffer. + (when (windowp window-to-paste) + (setq buf (window-buffer window-to-paste)) + (when (not (minibufferp buf)) + buf)))) + (setq cursor-in-text-area (and window-to-paste + point-to-paste + buffer-to-paste)) + + (when cursor-in-text-area + ;; Check if point under mouse is read-only. + (save-window-excursion + (select-window window-to-paste) + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq point-to-paste-read-only + (or buffer-read-only + (get-text-property point-to-paste 'read-only)))) + + ;; Check if "drag but negligible". Operation "drag but + ;; negligible" is defined as drag-and-drop the text to + ;; the original region. When modifier is pressed, the + ;; text will be inserted to inside of the original + ;; region. + (setq drag-but-negligible + (member mouse-drag-and-drop-region-face + (mapcar (lambda (xxx) (overlay-get xxx 'face)) + (overlays-at point-to-paste))))) + + ;; Show a tooltip. + (if (and mouse-drag-and-drop-region-show-tooltip + (not drag-but-negligible) + (not point-to-paste-read-only) + cursor-in-text-area) + (tooltip-show text-tooltip) + (tooltip-hide)) + + ;; Show cursor and highlight the original region. + (when mouse-drag-and-drop-region-show-cursor + ;; Modify cursor even when point is out of frame. + (setq cursor-type (cond + ((not cursor-in-text-area) + nil) + ((or point-to-paste-read-only + drag-but-negligible) + 'hollow) + (t + 'bar))) + (when cursor-in-text-area + (overlay-put mouse-drag-and-drop-overlay + 'face mouse-drag-and-drop-region-face) + (deactivate-mark) ; Maintain region in other window. + (mouse-set-point event))))) + + ;; Hide a tooltip. + (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide)) + + ;; Check if modifier was pressed on drop. + (setq no-modifier-on-drop + (not (member mouse-drag-and-drop-region (event-modifiers event)))) + + ;; Check if event was "click". + (setq clicked (not value-selection)) + + ;; Restore status on drag to outside of text-area or non-mouse input. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00486.html + (when (or (not cursor-in-text-area) + (not (equal (event-basic-type event) mouse-button))) + (setq drag-but-negligible t + no-modifier-on-drop t)) + + ;; Do not modify any buffers when event is "click", + ;; "drag but negligible", or "drag to read-only". + (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ + (if no-modifier-on-drop + mouse-drag-and-drop-region-cut-when-buffers-differ + (not mouse-drag-and-drop-region-cut-when-buffers-differ))) + (wanna-paste-to-same-buffer (equal buffer-to-paste buffer)) + (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer + no-modifier-on-drop)) + (wanna-cut-on-other-buffer (and (not wanna-paste-to-same-buffer) + mouse-drag-and-drop-region-cut-when-buffers-differ)) + (cannot-paste (or point-to-paste-read-only + (when (or wanna-cut-on-same-buffer + wanna-cut-on-other-buffer) + text-from-read-only)))) + + (cond + ;; Move point within region. + (clicked + (deactivate-mark) + (mouse-set-point event)) + ;; Undo operation. Set back the original text as region. + ((or (and drag-but-negligible + no-modifier-on-drop) + cannot-paste) + ;; Inform user either source or destination buffer cannot be modified. + (when (and (not drag-but-negligible) + cannot-paste) + (message "Buffer is read-only")) + + ;; Select source window back and restore region. + ;; (set-window-point window point) + (select-window window) + (goto-char point) + (setq deactivate-mark nil) + (activate-mark)) + ;; Modify buffers. + (t + ;; * DESTINATION BUFFER:: + ;; Insert the text to destination buffer under mouse. + (select-window window-to-paste) + (setq window-dropped window-to-paste) + (goto-char point-to-paste) + (push-mark) + (insert value-selection) + ;; On success, set the text as region on destination buffer. + (when (not (equal (mark) (point))) + (setq deactivate-mark nil) + (activate-mark)) + + ;; * SOURCE BUFFER:: + ;; Set back the original text as region or delete the original + ;; text, on source buffer. + (if wanna-paste-to-same-buffer + ;; When source buffer and destination buffer are the same, + ;; remove the original text. + (when no-modifier-on-drop + (let (deactivate-mark) + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)))) + ;; When source buffer and destination buffer are different, + ;; keep (set back the original text as region) or remove the + ;; original text. + (select-window window) ; Select window with source buffer. + (goto-char point) ; Move point to the original text on source buffer. + + (if mouse-drag-and-drop-region-cut-when-buffers-differ + ;; Remove the dragged text from source buffer like + ;; operation `cut'. + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)) + ;; Set back the dragged text as region on source buffer + ;; like operation `copy'. + (activate-mark)) + (select-window window-to-paste)))))) + (error nil)) + + ;; Clean up. + (delete-overlay mouse-drag-and-drop-overlay) + + ;; Restore old states but for the window where the drop + ;; occurred. Restore cursor types for all windows. + (dolist (state states) + (let ((window (car state))) + (unless (eq window window-dropped) + (set-window-start window (nth 1 state) 'noforce) + (set-marker (nth 1 state) nil) + ;; If window is selected, the following automatically sets + ;; point for that window's buffer. + (set-window-point window (nth 2 state)) + (set-marker (nth 2 state) nil)) + (with-current-buffer (window-buffer window) + (setq cursor-type (nth 3 state))))))) \f ;;; Bindings for mouse commands. ^ permalink raw reply related [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-05 4:57 ` mouse-drag-and-drop-region Tak Kunihiro @ 2017-12-05 8:53 ` martin rudalics 2017-12-06 9:29 ` mouse-drag-and-drop-region Tak Kunihiro 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-12-05 8:53 UTC (permalink / raw) To: Tak Kunihiro; +Cc: eliz, agrambot, emacs-devel > Thank you. I think that by your revision, the problem was solved. I > also revised code not to let user drop the text to minibuffer. Thanks. One issue I'm yet uncertain about: This part (if (and mouse-drag-and-drop-region-show-tooltip (not drag-but-negligible) (not point-to-paste-read-only) cursor-in-text-area) (tooltip-show text-tooltip) (tooltip-hide)) means that the tooltip text does not appear as long as the mouse is within the initial region (because there drag-but-negligible is non-nil, I presume). This comes somewhat unexpected - I'd expect the initial feedback via a tooltip to appear right away as soon as I start dragging. Personally, I'd even show the tooltip text when the mouse is temporarily out of the frame and leave it to the cursor to indicate whether a drop is possible at that position. But this is a personal preference - I'll check in whatever you prefer. > This > time, I attach a patch as a separated file. Highly appreciated. Applies without any problems now. >> Please consider also the following four bindings in `mouse-drag-track': >> >> (echo-keystrokes 0) I remember that occasionally during dragging some thing (I don't remember whether it does happen with the region) I see in the echo area text like down-mouse-1 or the like appear. If you see that too, this binding might be useful to suppress such feedback. >> >> (make-cursor-line-fully-visible nil) >> >> ;; Suppress automatic hscrolling, because that is a nuisance >> ;; when setting point near the right fringe (but see below). >> (auto-hscroll-mode-saved auto-hscroll-mode) Both of theses might have impact when you move the cursor to a position that is only partially visible at some border of the window. You might have to experiment, for example, by starting with a horizontally scrolled window or a window with point near the bottom to see the impact. >> (old-track-mouse track-mouse) This should handle the case where `mouse-drag-and-drop-region' intercepts an already ongoing track operation. I have no idea whether such a thing can happen in practice. >> Maybe they are useful for you as well (a lot of experience went into the >> coding of that function). > > I wonder if this is beyond my skill. Could you revise this part? I indicated above whether and why these may be useful. We probably should just wait until real problems show up in this regard. > It is a good idea. Now tooltip shows only substring. I think > mouse-drag-and-drop-region-show-tooltip should be something like 256 > by default. OK. >> Finally, please think of how to embed your function into other packages: >> For example, how would a user drag file names from one dired buffer to >> another in order to copy or move the associated files from one directory >> to another? Can we accomodate an exit function to do the pasting job? > > It is a good idea. I suppose you mean dragging `file' when > event-start is with 'dired-filename. Never using dired I have no idea. But ISTR that most two-pane file managers (aka Norton Commander clones) have some mouse support to do that. So it might be a good idea to think about how to incorporate such support right now. One issue with dired and customization buffers we probably have to resolve is the following: When `inhibit-read-only' is non-nil, we should allow cutting/pasting from/into read-only buffers or text. I've never looked into this matter. Maybe you can find some code which does handle that so we can steal it. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-05 8:53 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-06 9:29 ` Tak Kunihiro 2017-12-07 9:26 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Tak Kunihiro @ 2017-12-06 9:29 UTC (permalink / raw) To: rudalics; +Cc: eliz, tak.kunihiro, agrambot, emacs-devel [-- Attachment #1: Type: Text/Plain, Size: 1406 bytes --] Thank you for comments. > I'd expect the initial feedback via a tooltip to appear right away > as soon as I start dragging. Personally, I'd even show the tooltip > text when the mouse is temporarily out of the frame and leave it to > the cursor to indicate whether a drop is possible at that position. I think you are right. I revised the code back. >>> (echo-keystrokes 0) >>> (make-cursor-line-fully-visible nil) >>> (auto-hscroll-mode-saved auto-hscroll-mode) >>> (old-track-mouse track-mouse) > We probably should just wait until real problems show up in this > regard. Thank you for the comments. I agree. Let's postpone. > (dolist (state states) > (let ((window (car state))) > (unless (eq window window-dropped) > (set-window-start window (nth 1 state) 'noforce) > (set-marker (nth 1 state) nil) > ;; If window is selected, the following automatically sets > ;; point for that window's buffer. > (set-window-point window (nth 2 state)) > (set-marker (nth 2 state) nil)) > (with-current-buffer (window-buffer window) > (setq cursor-type (nth 3 state))))) I found a glitch. I think (unless (eq window window-dropped)... should be something like (when (and window-dropped (not (eq window window-dropped)))... . I attach the revise code. [-- Attachment #2: mouse.el.diff --] [-- Type: Text/X-Patch, Size: 16946 bytes --] diff --git a/lisp/mouse.el b/lisp/mouse.el index 17d1732..aacb550 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -2361,6 +2361,33 @@ text is copied instead of being cut." :version "26.1" :group 'mouse) +(defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil + "If non-nil, cut text also when source and destination buffers differ. +If this option is nil, `mouse-drag-and-drop-region' will leave +the text in the source buffer alone when dropping it in a +different buffer. If this is non-nil, it will cut the text just +as it does when dropping text in the source buffer." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-tooltip 256 + "If non-nil, text is shown by a tooltip in a graphic display. +If this option is an integer, such as 32 or 64, a number giving +the maximum length of the string shown in tooltip." + :type 'integer + :version "26.1" + :group 'mouse) + +(defvar mouse-drag-and-drop-region-show-cursor t + "If non-nil, move point with mouse cursor during dragging. +In addition, highlight the original region with +`mouse-drag-and-drop-region-face'.") + +(defvar mouse-drag-and-drop-region-face 'region + "Face to highlight the original text during dragging. +See also `mouse-drag-and-drop-region-show-cursor'.") + (defun mouse-drag-and-drop-region (event) "Move text in the region to point where mouse is dragged to. The transportation of text is also referred as `drag and drop'. @@ -2369,66 +2396,251 @@ modifier key was pressed when dropping, and the value of the variable `mouse-drag-and-drop-region' is that modifier, the text is copied instead of being cut." (interactive "e") - (require 'tooltip) - (let ((start (region-beginning)) - (end (region-end)) - (point (point)) - (buffer (current-buffer)) - (window (selected-window)) - value-selection) - (track-mouse - ;; When event was click instead of drag, skip loop - (while (progn - (setq event (read-event)) - (or (mouse-movement-p event) - ;; Handle `mouse-autoselect-window'. - (eq (car-safe event) 'select-window))) - (unless value-selection ; initialization - (delete-overlay mouse-secondary-overlay) - (setq value-selection (buffer-substring start end)) - (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) - (ignore-errors (deactivate-mark) ; care existing region in other window - (mouse-set-point event) - (tooltip-show value-selection))) - (tooltip-hide)) - ;; Do not modify buffer under mouse when "event was click", - ;; "drag negligible", or - ;; "drag to read-only". - (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" - (member 'secondary-selection ; "drag negligible" - (mapcar (lambda (xxx) (overlay-get xxx 'face)) - (overlays-at (posn-point (event-end event))))) - buffer-read-only) - ;; Do not modify buffer under mouse. - (cond - ;; "drag negligible" or "drag to read-only", restore region. - (value-selection - (select-window window) ; In case miss drag to other window - (goto-char point) - (setq deactivate-mark nil) - (activate-mark)) - ;; "event was click" - (t - (deactivate-mark) - (mouse-set-point event))) - ;; Modify buffer under mouse by inserting text. - (push-mark) - (insert value-selection) - (when (not (equal (mark) (point))) ; on success insert - (setq deactivate-mark nil) - (activate-mark)) ; have region on destination - ;; Take care of initial region on source. - (if (equal (current-buffer) buffer) ; when same buffer - (let (deactivate-mark) ; remove text - (unless (member mouse-drag-and-drop-region (event-modifiers event)) - (kill-region (overlay-start mouse-secondary-overlay) - (overlay-end mouse-secondary-overlay)))) - (let ((window1 (selected-window))) ; when beyond buffer - (select-window window) - (goto-char point) ; restore point on source window - (activate-mark) ; restore region - (select-window window1)))) - (delete-overlay mouse-secondary-overlay))) + (let* ((mouse-button (event-basic-type last-input-event)) + (mouse-drag-and-drop-region-show-tooltip + (when (and mouse-drag-and-drop-region-show-tooltip + (display-multi-frame-p) + (require 'tooltip)) + mouse-drag-and-drop-region-show-tooltip)) + (start (region-beginning)) + (end (region-end)) + (point (point)) + (buffer (current-buffer)) + (window (selected-window)) + (text-from-read-only buffer-read-only) + (mouse-drag-and-drop-overlay (make-overlay start end)) + point-to-paste + point-to-paste-read-only + window-to-paste + buffer-to-paste + cursor-in-text-area + no-modifier-on-drop + drag-but-negligible + clicked + value-selection ; This remains nil when event was "click". + text-tooltip + states + window-dropped) + + ;; STATES stores for each window on this frame its start and point + ;; positions so we can restore them on all windows but for the one + ;; where the drop occurs. For inter-frame drags we'll have to do + ;; this for all windows on all visible frames. In addition we save + ;; also the cursor type for the window's buffer so we can restore it + ;; in case we modified it. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-12/msg00090.html + (walk-window-tree + (lambda (window) + (setq states + (cons + (list + window + (copy-marker (window-start window)) + (copy-marker (window-point window)) + (with-current-buffer (window-buffer window) + cursor-type)) + states)))) + + (condition-case nil + (progn + (track-mouse + ;; When event was "click" instead of "drag", skip loop. + (while (progn + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00364.html + (setq event (read-key)) ; read-event or read-key + (or (mouse-movement-p event) + ;; Handle `mouse-autoselect-window'. + (eq (car-safe event) 'select-window))) + ;; Obtain the dragged text in region. When the loop was + ;; skipped, value-selection remains nil. + (unless value-selection + (setq value-selection (buffer-substring start end)) + (when mouse-drag-and-drop-region-show-tooltip + (let ((text-size mouse-drag-and-drop-region-show-tooltip)) + (setq text-tooltip (if (and (integerp text-size) + (> (length value-selection) text-size)) + (concat + (substring value-selection 0 (/ text-size 2)) + "\n...\n" + (substring value-selection (- (/ text-size 2)) -1)) + value-selection)))) + + ;; Check if selected text is read-only. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00663.html + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq text-from-read-only (or text-from-read-only + (get-text-property start 'read-only) + (not (equal + (next-single-char-property-change start 'read-only nil end) + end))))) + (setq window-to-paste (posn-window (event-end event))) + (setq point-to-paste (posn-point (event-end event))) + (setq buffer-to-paste (let (buf) ; Set nil when target buffer is minibuffer. + (when (windowp window-to-paste) + (setq buf (window-buffer window-to-paste)) + (when (not (minibufferp buf)) + buf)))) + (setq cursor-in-text-area (and window-to-paste + point-to-paste + buffer-to-paste)) + + (when cursor-in-text-area + ;; Check if point under mouse is read-only. + (save-window-excursion + (select-window window-to-paste) + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq point-to-paste-read-only + (or buffer-read-only + (get-text-property point-to-paste 'read-only)))) + + ;; Check if "drag but negligible". Operation "drag but + ;; negligible" is defined as drag-and-drop the text to + ;; the original region. When modifier is pressed, the + ;; text will be inserted to inside of the original + ;; region. + (setq drag-but-negligible + (member mouse-drag-and-drop-region-face + (mapcar (lambda (xxx) (overlay-get xxx 'face)) + (overlays-at point-to-paste))))) + + ;; Show a tooltip. + (if mouse-drag-and-drop-region-show-tooltip + ;; (and mouse-drag-and-drop-region-show-tooltip + ;; (not drag-but-negligible) + ;; (not point-to-paste-read-only) + ;; cursor-in-text-area) + (tooltip-show text-tooltip) + (tooltip-hide)) + + ;; Show cursor and highlight the original region. + (when mouse-drag-and-drop-region-show-cursor + ;; Modify cursor even when point is out of frame. + (setq cursor-type (cond + ((not cursor-in-text-area) + nil) + ((or point-to-paste-read-only + drag-but-negligible) + 'hollow) + (t + 'bar))) + (when cursor-in-text-area + (overlay-put mouse-drag-and-drop-overlay + 'face mouse-drag-and-drop-region-face) + (deactivate-mark) ; Maintain region in other window. + (mouse-set-point event))))) + + ;; Hide a tooltip. + (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide)) + + ;; Check if modifier was pressed on drop. + (setq no-modifier-on-drop + (not (member mouse-drag-and-drop-region (event-modifiers event)))) + + ;; Check if event was "click". + (setq clicked (not value-selection)) + + ;; Restore status on drag to outside of text-area or non-mouse input. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00486.html + (when (or (not cursor-in-text-area) + (not (equal (event-basic-type event) mouse-button))) + (setq drag-but-negligible t + no-modifier-on-drop t)) + + ;; Do not modify any buffers when event is "click", + ;; "drag but negligible", or "drag to read-only". + (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ + (if no-modifier-on-drop + mouse-drag-and-drop-region-cut-when-buffers-differ + (not mouse-drag-and-drop-region-cut-when-buffers-differ))) + (wanna-paste-to-same-buffer (equal buffer-to-paste buffer)) + (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer + no-modifier-on-drop)) + (wanna-cut-on-other-buffer (and (not wanna-paste-to-same-buffer) + mouse-drag-and-drop-region-cut-when-buffers-differ)) + (cannot-paste (or point-to-paste-read-only + (when (or wanna-cut-on-same-buffer + wanna-cut-on-other-buffer) + text-from-read-only)))) + + (cond + ;; Move point within region. + (clicked + (deactivate-mark) + (mouse-set-point event)) + ;; Undo operation. Set back the original text as region. + ((or (and drag-but-negligible + no-modifier-on-drop) + cannot-paste) + ;; Inform user either source or destination buffer cannot be modified. + (when (and (not drag-but-negligible) + cannot-paste) + (message "Buffer is read-only")) + + ;; Select source window back and restore region. + ;; (set-window-point window point) + (select-window window) + (goto-char point) + (setq deactivate-mark nil) + (activate-mark)) + ;; Modify buffers. + (t + ;; * DESTINATION BUFFER:: + ;; Insert the text to destination buffer under mouse. + (select-window window-to-paste) + (setq window-dropped window-to-paste) + (goto-char point-to-paste) + (push-mark) + (insert value-selection) + ;; On success, set the text as region on destination buffer. + (when (not (equal (mark) (point))) + (setq deactivate-mark nil) + (activate-mark)) + + ;; * SOURCE BUFFER:: + ;; Set back the original text as region or delete the original + ;; text, on source buffer. + (if wanna-paste-to-same-buffer + ;; When source buffer and destination buffer are the same, + ;; remove the original text. + (when no-modifier-on-drop + (let (deactivate-mark) + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)))) + ;; When source buffer and destination buffer are different, + ;; keep (set back the original text as region) or remove the + ;; original text. + (select-window window) ; Select window with source buffer. + (goto-char point) ; Move point to the original text on source buffer. + + (if mouse-drag-and-drop-region-cut-when-buffers-differ + ;; Remove the dragged text from source buffer like + ;; operation `cut'. + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)) + ;; Set back the dragged text as region on source buffer + ;; like operation `copy'. + (activate-mark)) + (select-window window-to-paste)))))) + (error nil)) + + ;; Clean up. + (delete-overlay mouse-drag-and-drop-overlay) + + ;; Restore old states but for the window where the drop + ;; occurred. Restore cursor types for all windows. + (dolist (state states) + (let ((window (car state))) + (when (and window-dropped + (not (eq window window-dropped))) + ;; unless (eq window window-dropped) + (set-window-start window (nth 1 state) 'noforce) + (set-marker (nth 1 state) nil) + ;; If window is selected, the following automatically sets + ;; point for that window's buffer. + (set-window-point window (nth 2 state)) + (set-marker (nth 2 state) nil)) + (with-current-buffer (window-buffer window) + (setq cursor-type (nth 3 state))))))) \f ;;; Bindings for mouse commands. ^ permalink raw reply related [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-06 9:29 ` mouse-drag-and-drop-region Tak Kunihiro @ 2017-12-07 9:26 ` martin rudalics 2017-12-07 21:45 ` mouse-drag-and-drop-region Tak Kunihiro 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-12-07 9:26 UTC (permalink / raw) To: Tak Kunihiro; +Cc: eliz, agrambot, emacs-devel > I found a glitch. I think > > (unless (eq window window-dropped)... > > should be something like > > (when (and window-dropped > (not (eq window window-dropped)))... Wouldn't this mean that when window-dropped is nil and the user has changed the point of some other window, that other's window point is not reverted to its original position? I think the (unless (eq window window-dropped) DTRT: WINDOW cannot be nil here and if it equals WINDOW-DROPPED then we should not revert its point. Or am I missing something? But to relax indentation we should turn the + (condition-case nil + (progn ... + (error nil)) into either (ignore-errors ...) or the more informative (with-demoted-errors "mouse-drag-and-drop-region error: %s" ...) whichever you prefer. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-07 9:26 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-07 21:45 ` Tak Kunihiro 2017-12-08 10:12 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Tak Kunihiro @ 2017-12-07 21:45 UTC (permalink / raw) To: rudalics; +Cc: eliz, tak.kunihiro, agrambot, emacs-devel >> I found a glitch. I think >> >> (unless (eq window window-dropped)... >> >> should be something like >> >> (when (and window-dropped >> (not (eq window window-dropped)))... > > Wouldn't this mean that when window-dropped is nil and the user has > changed the point of some other window, that other's window point is > not reverted to its original position? I think the > > (unless (eq window window-dropped) > > DTRT: WINDOW cannot be nil here and if it equals WINDOW-DROPPED then > we should not revert its point. Or am I missing something? When the user just clicks within the region (no drag), window-dropped remains nil. On such condition, window-start should not be set. Let's say there are two window top and bottom (T and B) in a frame. Scroll T to the end. Make region in B. Then click the region. I will see T to be scrolled to the beginning. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-07 21:45 ` mouse-drag-and-drop-region Tak Kunihiro @ 2017-12-08 10:12 ` martin rudalics 2017-12-08 16:14 ` mouse-drag-and-drop-region Robert Weiner 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-12-08 10:12 UTC (permalink / raw) To: Tak Kunihiro; +Cc: eliz, agrambot, emacs-devel > When the user just clicks within the region (no drag), window-dropped > remains nil. On such condition, window-start should not be set. > > Let's say there are two window top and bottom (T and B) in a frame. > Scroll T to the end. Make region in B. Then click the region. I > will see T to be scrolled to the beginning. Aha... Then let's rename window-dropped to something like window-exempt and set window-exempt to the window either clicked at or where the drop occurs. Would that be OK? martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-08 10:12 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-08 16:14 ` Robert Weiner 2017-12-09 10:35 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Robert Weiner @ 2017-12-08 16:14 UTC (permalink / raw) To: martin rudalics; +Cc: Eli Zaretskii, Tak Kunihiro, Alex, emacs-devel [-- Attachment #1: Type: text/plain, Size: 806 bytes --] On Fri, Dec 8, 2017 at 5:12 AM, martin rudalics <rudalics@gmx.at> wrote: > > When the user just clicks within the region (no drag), window-dropped > > remains nil. On such condition, window-start should not be set. > > > > Let's say there are two window top and bottom (T and B) in a frame. > > Scroll T to the end. Make region in B. Then click the region. I > > will see T to be scrolled to the beginning. > > Aha... Then let's rename window-dropped to something like window-exempt > and set window-exempt to the window either clicked at or where the drop > occurs. Would that be OK? Better names might be droppped-window or destination-window. If this is nil, then no drag-and-drop occurred; otherwise, it is the window of the drop, so why call it window-exempt? Bob [-- Attachment #2: Type: text/html, Size: 1808 bytes --] ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-08 16:14 ` mouse-drag-and-drop-region Robert Weiner @ 2017-12-09 10:35 ` martin rudalics 2017-12-14 23:14 ` mouse-drag-and-drop-region Tak Kunihiro 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-12-09 10:35 UTC (permalink / raw) To: rswgnu; +Cc: Eli Zaretskii, Tak Kunihiro, Alex, emacs-devel > Better names might be droppped-window or destination-window. > If this is nil, then no drag-and-drop occurred; otherwise, > it is the window of the drop, so why call it window-exempt? Because the click or drop exempts that window from the point restoration mechanism. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-09 10:35 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-14 23:14 ` Tak Kunihiro 2017-12-15 8:50 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Tak Kunihiro @ 2017-12-14 23:14 UTC (permalink / raw) To: martin rudalics; +Cc: rswgnu, Eli Zaretskii, Kunihiro Tak, Alex, emacs-devel [-- Attachment #1: Type: text/plain, Size: 1800 bytes --] I re-re-re-revised mouse-drag-and-drop-region. I'm sending reply to https://lists.gnu.org/archive/html/emacs-devel/2017-12/msg00258.html, ChangeLog, and patch. * ChangeLog 2017-12-16 Tak Kunihiro <tkk@misasa.okayama-u.ac.jp> Improve comments and have four new options * lisp/mouse.el (mouse-drag-and-drop-region): Have option to make dragging cut among buffers. Make usage of tooltip option. (mouse-drag-and-drop-region-cut-when-buffers-differ): New variable. If non-nil, text is cut instead of copied when dragged among buffers. (mouse-drag-and-drop-region-show-tooltip): New variable. If non-nil, text is shown by tooltip in a graphic display. (mouse-drag-and-drop-region-show-cursor): New variable. If non-nil, point is set to where the mouse cursor. (mouse-drag-and-drop-region-face): New variable for face. The face is used to highlight the original text. * Reply >>> When the user just clicks within the region (no drag), window-dropped >>> remains nil. On such condition, window-start should not be set. >>> >>> Let's say there are two window top and bottom (T and B) in a frame. >>> Scroll T to the end. Make region in B. Then click the region. I >>> will see T to be scrolled to the beginning. >> >> Then let's rename window-dropped to something like window-exempt >> and set window-exempt to the window either clicked at or where the drop >> occurs. > >> Better names might be droppped-window or destination-window. >> If this is nil, then no drag-and-drop occurred; otherwise, >> it is the window of the drop, so why call it window-exempt? > > Because the click or drop exempts that window from the point restoration > mechanism. OK. I changed from `window-dropped' to `window-exempt’. [-- Attachment #2: mouse.el.diff --] [-- Type: application/octet-stream, Size: 17243 bytes --] diff --git a/lisp/mouse.el b/lisp/mouse.el index 17d1732..bc56448 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -2361,6 +2361,33 @@ text is copied instead of being cut." :version "26.1" :group 'mouse) +(defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil + "If non-nil, cut text also when source and destination buffers differ. +If this option is nil, `mouse-drag-and-drop-region' will leave +the text in the source buffer alone when dropping it in a +different buffer. If this is non-nil, it will cut the text just +as it does when dropping text in the source buffer." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-tooltip 256 + "If non-nil, text is shown by a tooltip in a graphic display. +If this option is an integer, such as 32 or 64, a number giving +the maximum length of the string shown in tooltip." + :type 'integer + :version "26.1" + :group 'mouse) + +(defvar mouse-drag-and-drop-region-show-cursor t + "If non-nil, move point with mouse cursor during dragging. +In addition, highlight the original region with +`mouse-drag-and-drop-region-face'.") + +(defvar mouse-drag-and-drop-region-face 'region + "Face to highlight the original text during dragging. +See also `mouse-drag-and-drop-region-show-cursor'.") + (defun mouse-drag-and-drop-region (event) "Move text in the region to point where mouse is dragged to. The transportation of text is also referred as `drag and drop'. @@ -2369,66 +2396,250 @@ modifier key was pressed when dropping, and the value of the variable `mouse-drag-and-drop-region' is that modifier, the text is copied instead of being cut." (interactive "e") - (require 'tooltip) - (let ((start (region-beginning)) - (end (region-end)) - (point (point)) - (buffer (current-buffer)) - (window (selected-window)) - value-selection) - (track-mouse - ;; When event was click instead of drag, skip loop - (while (progn - (setq event (read-event)) - (or (mouse-movement-p event) - ;; Handle `mouse-autoselect-window'. - (eq (car-safe event) 'select-window))) - (unless value-selection ; initialization - (delete-overlay mouse-secondary-overlay) - (setq value-selection (buffer-substring start end)) - (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) - (ignore-errors (deactivate-mark) ; care existing region in other window - (mouse-set-point event) - (tooltip-show value-selection))) - (tooltip-hide)) - ;; Do not modify buffer under mouse when "event was click", - ;; "drag negligible", or - ;; "drag to read-only". - (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" - (member 'secondary-selection ; "drag negligible" - (mapcar (lambda (xxx) (overlay-get xxx 'face)) - (overlays-at (posn-point (event-end event))))) - buffer-read-only) - ;; Do not modify buffer under mouse. - (cond - ;; "drag negligible" or "drag to read-only", restore region. - (value-selection - (select-window window) ; In case miss drag to other window - (goto-char point) - (setq deactivate-mark nil) - (activate-mark)) - ;; "event was click" - (t - (deactivate-mark) - (mouse-set-point event))) - ;; Modify buffer under mouse by inserting text. - (push-mark) - (insert value-selection) - (when (not (equal (mark) (point))) ; on success insert - (setq deactivate-mark nil) - (activate-mark)) ; have region on destination - ;; Take care of initial region on source. - (if (equal (current-buffer) buffer) ; when same buffer - (let (deactivate-mark) ; remove text - (unless (member mouse-drag-and-drop-region (event-modifiers event)) - (kill-region (overlay-start mouse-secondary-overlay) - (overlay-end mouse-secondary-overlay)))) - (let ((window1 (selected-window))) ; when beyond buffer - (select-window window) - (goto-char point) ; restore point on source window - (activate-mark) ; restore region - (select-window window1)))) - (delete-overlay mouse-secondary-overlay))) + (let* ((mouse-button (event-basic-type last-input-event)) + (mouse-drag-and-drop-region-show-tooltip + (when (and mouse-drag-and-drop-region-show-tooltip + (display-multi-frame-p) + (require 'tooltip)) + mouse-drag-and-drop-region-show-tooltip)) + (start (region-beginning)) + (end (region-end)) + (point (point)) + (buffer (current-buffer)) + (window (selected-window)) + (text-from-read-only buffer-read-only) + (mouse-drag-and-drop-overlay (make-overlay start end)) + point-to-paste + point-to-paste-read-only + window-to-paste + buffer-to-paste + cursor-in-text-area + no-modifier-on-drop + drag-but-negligible + clicked + value-selection ; This remains nil when event was "click". + text-tooltip + states + window-exempt) + + ;; STATES stores for each window on this frame its start and point + ;; positions so we can restore them on all windows but for the one + ;; where the drop occurs. For inter-frame drags we'll have to do + ;; this for all windows on all visible frames. In addition we save + ;; also the cursor type for the window's buffer so we can restore it + ;; in case we modified it. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-12/msg00090.html + (walk-window-tree + (lambda (window) + (setq states + (cons + (list + window + (copy-marker (window-start window)) + (copy-marker (window-point window)) + (with-current-buffer (window-buffer window) + cursor-type)) + states)))) + + (condition-case nil + (progn + (track-mouse + ;; When event was "click" instead of "drag", skip loop. + (while (progn + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00364.html + (setq event (read-key)) ; read-event or read-key + (or (mouse-movement-p event) + ;; Handle `mouse-autoselect-window'. + (eq (car-safe event) 'select-window))) + ;; Obtain the dragged text in region. When the loop was + ;; skipped, value-selection remains nil. + (unless value-selection + (setq value-selection (buffer-substring start end)) + (when mouse-drag-and-drop-region-show-tooltip + (let ((text-size mouse-drag-and-drop-region-show-tooltip)) + (setq text-tooltip (if (and (integerp text-size) + (> (length value-selection) text-size)) + (concat + (substring value-selection 0 (/ text-size 2)) + "\n...\n" + (substring value-selection (- (/ text-size 2)) -1)) + value-selection)))) + + ;; Check if selected text is read-only. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00663.html + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq text-from-read-only (or text-from-read-only + (get-text-property start 'read-only) + (not (equal + (next-single-char-property-change start 'read-only nil end) + end))))) + (setq window-to-paste (posn-window (event-end event))) + (setq point-to-paste (posn-point (event-end event))) + (setq buffer-to-paste (let (buf) ; Set nil when target buffer is minibuffer. + (when (windowp window-to-paste) + (setq buf (window-buffer window-to-paste)) + (when (not (minibufferp buf)) + buf)))) + (setq cursor-in-text-area (and window-to-paste + point-to-paste + buffer-to-paste)) + + (when cursor-in-text-area + ;; Check if point under mouse is read-only. + (save-window-excursion + (select-window window-to-paste) + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq point-to-paste-read-only + (or buffer-read-only + (get-text-property point-to-paste 'read-only)))) + + ;; Check if "drag but negligible". Operation "drag but + ;; negligible" is defined as drag-and-drop the text to + ;; the original region. When modifier is pressed, the + ;; text will be inserted to inside of the original + ;; region. + (setq drag-but-negligible + (member mouse-drag-and-drop-region-face + (mapcar (lambda (xxx) (overlay-get xxx 'face)) + (overlays-at point-to-paste))))) + + ;; Show a tooltip. + (if mouse-drag-and-drop-region-show-tooltip + ;; (and mouse-drag-and-drop-region-show-tooltip + ;; (not drag-but-negligible) + ;; (not point-to-paste-read-only) + ;; cursor-in-text-area) + (tooltip-show text-tooltip) + (tooltip-hide)) + + ;; Show cursor and highlight the original region. + (when mouse-drag-and-drop-region-show-cursor + ;; Modify cursor even when point is out of frame. + (setq cursor-type (cond + ((not cursor-in-text-area) + nil) + ((or point-to-paste-read-only + drag-but-negligible) + 'hollow) + (t + 'bar))) + (when cursor-in-text-area + (overlay-put mouse-drag-and-drop-overlay + 'face mouse-drag-and-drop-region-face) + (deactivate-mark) ; Maintain region in other window. + (mouse-set-point event))))) + + ;; Hide a tooltip. + (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide)) + + ;; Check if modifier was pressed on drop. + (setq no-modifier-on-drop + (not (member mouse-drag-and-drop-region (event-modifiers event)))) + + ;; Check if event was "click". + (setq clicked (not value-selection)) + + ;; Restore status on drag to outside of text-area or non-mouse input. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00486.html + (when (or (not cursor-in-text-area) + (not (equal (event-basic-type event) mouse-button))) + (setq drag-but-negligible t + no-modifier-on-drop t)) + + ;; Do not modify any buffers when event is "click", + ;; "drag but negligible", or "drag to read-only". + (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ + (if no-modifier-on-drop + mouse-drag-and-drop-region-cut-when-buffers-differ + (not mouse-drag-and-drop-region-cut-when-buffers-differ))) + (wanna-paste-to-same-buffer (equal buffer-to-paste buffer)) + (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer + no-modifier-on-drop)) + (wanna-cut-on-other-buffer (and (not wanna-paste-to-same-buffer) + mouse-drag-and-drop-region-cut-when-buffers-differ)) + (cannot-paste (or point-to-paste-read-only + (when (or wanna-cut-on-same-buffer + wanna-cut-on-other-buffer) + text-from-read-only)))) + + (cond + ;; Move point within region. + (clicked + (deactivate-mark) + (mouse-set-point event)) + ;; Undo operation. Set back the original text as region. + ((or (and drag-but-negligible + no-modifier-on-drop) + cannot-paste) + ;; Inform user either source or destination buffer cannot be modified. + (when (and (not drag-but-negligible) + cannot-paste) + (message "Buffer is read-only")) + + ;; Select source window back and restore region. + ;; (set-window-point window point) + (select-window window) + (goto-char point) + (setq deactivate-mark nil) + (activate-mark)) + ;; Modify buffers. + (t + ;; * DESTINATION BUFFER:: + ;; Insert the text to destination buffer under mouse. + (select-window window-to-paste) + (setq window-exempt window-to-paste) + (goto-char point-to-paste) + (push-mark) + (insert value-selection) + ;; On success, set the text as region on destination buffer. + (when (not (equal (mark) (point))) + (setq deactivate-mark nil) + (activate-mark)) + + ;; * SOURCE BUFFER:: + ;; Set back the original text as region or delete the original + ;; text, on source buffer. + (if wanna-paste-to-same-buffer + ;; When source buffer and destination buffer are the same, + ;; remove the original text. + (when no-modifier-on-drop + (let (deactivate-mark) + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)))) + ;; When source buffer and destination buffer are different, + ;; keep (set back the original text as region) or remove the + ;; original text. + (select-window window) ; Select window with source buffer. + (goto-char point) ; Move point to the original text on source buffer. + + (if mouse-drag-and-drop-region-cut-when-buffers-differ + ;; Remove the dragged text from source buffer like + ;; operation `cut'. + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)) + ;; Set back the dragged text as region on source buffer + ;; like operation `copy'. + (activate-mark)) + (select-window window-to-paste)))))) + (error nil)) + + ;; Clean up. + (delete-overlay mouse-drag-and-drop-overlay) + + ;; Restore old states but for the window where the drop + ;; occurred. Restore cursor types for all windows. + (dolist (state states) + (let ((window (car state))) + (when (and window-exempt + (not (eq window window-exempt))) + (set-window-start window (nth 1 state) 'noforce) + (set-marker (nth 1 state) nil) + ;; If window is selected, the following automatically sets + ;; point for that window's buffer. + (set-window-point window (nth 2 state)) + (set-marker (nth 2 state) nil)) + (with-current-buffer (window-buffer window) + (setq cursor-type (nth 3 state))))))) \f ;;; Bindings for mouse commands. ^ permalink raw reply related [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-14 23:14 ` mouse-drag-and-drop-region Tak Kunihiro @ 2017-12-15 8:50 ` martin rudalics 2017-12-15 13:25 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-12-15 8:50 UTC (permalink / raw) To: Tak Kunihiro; +Cc: Eli Zaretskii, rswgnu, Alex, emacs-devel [-- Attachment #1: Type: text/plain, Size: 1312 bytes --] > I re-re-re-revised mouse-drag-and-drop-region. I'm sending reply to https://lists.gnu.org/archive/html/emacs-devel/2017-12/msg00258.html, ChangeLog, and patch. > > * ChangeLog > > 2017-12-16 Tak Kunihiro <tkk@misasa.okayama-u.ac.jp> > > Improve comments and have four new options > > * lisp/mouse.el (mouse-drag-and-drop-region): Have option to make dragging cut among buffers. Make usage of tooltip option. > (mouse-drag-and-drop-region-cut-when-buffers-differ): New variable. If non-nil, text is cut instead of copied when dragged among buffers. > (mouse-drag-and-drop-region-show-tooltip): New variable. If non-nil, text is shown by tooltip in a graphic display. > (mouse-drag-and-drop-region-show-cursor): New variable. If non-nil, point is set to where the mouse cursor. > (mouse-drag-and-drop-region-face): New variable for face. The face is used to highlight the original text. Thanks. I resend you yet another revised version which mostly fixes the doc-strings of these options and replaces the option `mouse-drag-and-drop-region-face' with a face `mouse-drag-and-drop-region' inheriting from the region face. Please have a look. Unless you or someone else sees problems, I will install it. Thanks again for your efforts, martin [-- Attachment #2: mouse.el.diff --] [-- Type: text/plain, Size: 17171 bytes --] --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -2345,10 +2345,10 @@ mouse-appearance-menu \f ;; Drag and drop support. (defcustom mouse-drag-and-drop-region nil - "If non-nil, dragging the mouse drags the region, if that exists. -If the value is a modifier, such as `control' or `shift' or `meta', -then if that modifier key is pressed when dropping the region, region -text is copied instead of being cut." + "If non-nil, dragging the mouse drags the region, if it exists. +If the value is a modifier, such as `control' or `shift' or +`meta', then if that modifier key is pressed when dropping the +region, text is copied instead of being cut." :type `(choice (const :tag "Disable dragging the region" nil) ,@(mapcar @@ -2361,6 +2361,45 @@ mouse-drag-and-drop-region :version "26.1" :group 'mouse) +(defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil + "If non-nil, cut text also when source and destination buffers differ. +If this option is nil, `mouse-drag-and-drop-region' will leave +the text in the source buffer alone when dropping it in a +different buffer. If this is non-nil, it will cut the text just +as it does when dropping text in the source buffer." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-tooltip 256 + "If non-nil, text is shown by a tooltip in a graphic display. +If this option is nil, `mouse-drag-and-drop-region' does not show +tooltips. If this is t, it shows the entire text dragged in a +tooltip. If this is an integer (as with the default value of +256), it will show that many characters of the dragged text in +a tooltip." + :type 'integer + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-cursor t + "If non-nil, move point with mouse cursor during dragging. +If this is nil, `mouse-drag-and-drop-region' leaves point alone. +Otherwise, it will move point together with the mouse cursor and, +in addition, temporarily highlight the original region with the +`mouse-drag-and-drop-region' face." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defface mouse-drag-and-drop-region '((t :inherit region)) + "Face to highlight original text during dragging. +This face is used by `mouse-drag-and-drop-region' to temporarily +highlight the original region when +`mouse-drag-and-drop-region-show-cursor' is non-nil." + :version "26.1" + :group 'mouse) + (defun mouse-drag-and-drop-region (event) "Move text in the region to point where mouse is dragged to. The transportation of text is also referred as `drag and drop'. @@ -2369,66 +2408,248 @@ mouse-drag-and-drop-region variable `mouse-drag-and-drop-region' is that modifier, the text is copied instead of being cut." (interactive "e") - (require 'tooltip) - (let ((start (region-beginning)) - (end (region-end)) - (point (point)) - (buffer (current-buffer)) - (window (selected-window)) - value-selection) - (track-mouse - ;; When event was click instead of drag, skip loop - (while (progn - (setq event (read-event)) - (or (mouse-movement-p event) - ;; Handle `mouse-autoselect-window'. - (eq (car-safe event) 'select-window))) - (unless value-selection ; initialization - (delete-overlay mouse-secondary-overlay) - (setq value-selection (buffer-substring start end)) - (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) - (ignore-errors (deactivate-mark) ; care existing region in other window - (mouse-set-point event) - (tooltip-show value-selection))) - (tooltip-hide)) - ;; Do not modify buffer under mouse when "event was click", - ;; "drag negligible", or - ;; "drag to read-only". - (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" - (member 'secondary-selection ; "drag negligible" - (mapcar (lambda (xxx) (overlay-get xxx 'face)) - (overlays-at (posn-point (event-end event))))) - buffer-read-only) - ;; Do not modify buffer under mouse. + (let* ((mouse-button (event-basic-type last-input-event)) + (mouse-drag-and-drop-region-show-tooltip + (when (and mouse-drag-and-drop-region-show-tooltip + (display-multi-frame-p) + (require 'tooltip)) + mouse-drag-and-drop-region-show-tooltip)) + (start (region-beginning)) + (end (region-end)) + (point (point)) + (buffer (current-buffer)) + (window (selected-window)) + (text-from-read-only buffer-read-only) + (mouse-drag-and-drop-overlay (make-overlay start end)) + point-to-paste + point-to-paste-read-only + window-to-paste + buffer-to-paste + cursor-in-text-area + no-modifier-on-drop + drag-but-negligible + clicked + value-selection ; This remains nil when event was "click". + text-tooltip + states + window-exempt) + + ;; STATES stores for each window on this frame its start and point + ;; positions so we can restore them on all windows but for the one + ;; where the drop occurs. For inter-frame drags we'll have to do + ;; this for all windows on all visible frames. In addition we save + ;; also the cursor type for the window's buffer so we can restore it + ;; in case we modified it. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-12/msg00090.html + (walk-window-tree + (lambda (window) + (setq states + (cons + (list + window + (copy-marker (window-start window)) + (copy-marker (window-point window)) + (with-current-buffer (window-buffer window) + cursor-type)) + states)))) + + (ignore-errors + (track-mouse + ;; When event was "click" instead of "drag", skip loop. + (while (progn + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00364.html + (setq event (read-key)) ; read-event or read-key + (or (mouse-movement-p event) + ;; Handle `mouse-autoselect-window'. + (eq (car-safe event) 'select-window))) + ;; Obtain the dragged text in region. When the loop was + ;; skipped, value-selection remains nil. + (unless value-selection + (setq value-selection (buffer-substring start end)) + (when mouse-drag-and-drop-region-show-tooltip + (let ((text-size mouse-drag-and-drop-region-show-tooltip)) + (setq text-tooltip (if (and (integerp text-size) + (> (length value-selection) text-size)) + (concat + (substring value-selection 0 (/ text-size 2)) + "\n...\n" + (substring value-selection (- (/ text-size 2)) -1)) + value-selection)))) + + ;; Check if selected text is read-only. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00663.html + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq text-from-read-only (or text-from-read-only + (get-text-property start 'read-only) + (not (equal + (next-single-char-property-change start 'read-only nil end) + end))))) + (setq window-to-paste (posn-window (event-end event))) + (setq point-to-paste (posn-point (event-end event))) + (setq buffer-to-paste (let (buf) ; Set nil when target buffer is minibuffer. + (when (windowp window-to-paste) + (setq buf (window-buffer window-to-paste)) + (when (not (minibufferp buf)) + buf)))) + (setq cursor-in-text-area (and window-to-paste + point-to-paste + buffer-to-paste)) + + (when cursor-in-text-area + ;; Check if point under mouse is read-only. + (save-window-excursion + (select-window window-to-paste) + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq point-to-paste-read-only + (or buffer-read-only + (get-text-property point-to-paste 'read-only)))) + + ;; Check if "drag but negligible". Operation "drag but + ;; negligible" is defined as drag-and-drop the text to + ;; the original region. When modifier is pressed, the + ;; text will be inserted to inside of the original + ;; region. + (setq drag-but-negligible + (member mouse-drag-and-drop-region + (mapcar (lambda (xxx) (overlay-get xxx 'face)) + (overlays-at point-to-paste))))) + + ;; Show a tooltip. + (if mouse-drag-and-drop-region-show-tooltip + ;; (and mouse-drag-and-drop-region-show-tooltip + ;; (not drag-but-negligible) + ;; (not point-to-paste-read-only) + ;; cursor-in-text-area) + (tooltip-show text-tooltip) + (tooltip-hide)) + + ;; Show cursor and highlight the original region. + (when mouse-drag-and-drop-region-show-cursor + ;; Modify cursor even when point is out of frame. + (setq cursor-type (cond + ((not cursor-in-text-area) + nil) + ((or point-to-paste-read-only + drag-but-negligible) + 'hollow) + (t + 'bar))) + (when cursor-in-text-area + (overlay-put mouse-drag-and-drop-overlay + 'face mouse-drag-and-drop-region) + (deactivate-mark) ; Maintain region in other window. + (mouse-set-point event))))) + + ;; Hide a tooltip. + (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide)) + + ;; Check if modifier was pressed on drop. + (setq no-modifier-on-drop + (not (member mouse-drag-and-drop-region (event-modifiers event)))) + + ;; Check if event was "click". + (setq clicked (not value-selection)) + + ;; Restore status on drag to outside of text-area or non-mouse input. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00486.html + (when (or (not cursor-in-text-area) + (not (equal (event-basic-type event) mouse-button))) + (setq drag-but-negligible t + no-modifier-on-drop t)) + + ;; Do not modify any buffers when event is "click", + ;; "drag but negligible", or "drag to read-only". + (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ + (if no-modifier-on-drop + mouse-drag-and-drop-region-cut-when-buffers-differ + (not mouse-drag-and-drop-region-cut-when-buffers-differ))) + (wanna-paste-to-same-buffer (equal buffer-to-paste buffer)) + (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer + no-modifier-on-drop)) + (wanna-cut-on-other-buffer (and (not wanna-paste-to-same-buffer) + mouse-drag-and-drop-region-cut-when-buffers-differ)) + (cannot-paste (or point-to-paste-read-only + (when (or wanna-cut-on-same-buffer + wanna-cut-on-other-buffer) + text-from-read-only)))) + (cond - ;; "drag negligible" or "drag to read-only", restore region. - (value-selection - (select-window window) ; In case miss drag to other window + ;; Move point within region. + (clicked + (deactivate-mark) + (mouse-set-point event)) + ;; Undo operation. Set back the original text as region. + ((or (and drag-but-negligible + no-modifier-on-drop) + cannot-paste) + ;; Inform user either source or destination buffer cannot be modified. + (when (and (not drag-but-negligible) + cannot-paste) + (message "Buffer is read-only")) + + ;; Select source window back and restore region. + ;; (set-window-point window point) + (select-window window) (goto-char point) (setq deactivate-mark nil) (activate-mark)) - ;; "event was click" + ;; Modify buffers. (t - (deactivate-mark) - (mouse-set-point event))) - ;; Modify buffer under mouse by inserting text. - (push-mark) - (insert value-selection) - (when (not (equal (mark) (point))) ; on success insert - (setq deactivate-mark nil) - (activate-mark)) ; have region on destination - ;; Take care of initial region on source. - (if (equal (current-buffer) buffer) ; when same buffer - (let (deactivate-mark) ; remove text - (unless (member mouse-drag-and-drop-region (event-modifiers event)) - (kill-region (overlay-start mouse-secondary-overlay) - (overlay-end mouse-secondary-overlay)))) - (let ((window1 (selected-window))) ; when beyond buffer - (select-window window) - (goto-char point) ; restore point on source window - (activate-mark) ; restore region - (select-window window1)))) - (delete-overlay mouse-secondary-overlay))) + ;; * DESTINATION BUFFER:: + ;; Insert the text to destination buffer under mouse. + (select-window window-to-paste) + (setq window-exempt window-to-paste) + (goto-char point-to-paste) + (push-mark) + (insert value-selection) + ;; On success, set the text as region on destination buffer. + (when (not (equal (mark) (point))) + (setq deactivate-mark nil) + (activate-mark)) + + ;; * SOURCE BUFFER:: + ;; Set back the original text as region or delete the original + ;; text, on source buffer. + (if wanna-paste-to-same-buffer + ;; When source buffer and destination buffer are the same, + ;; remove the original text. + (when no-modifier-on-drop + (let (deactivate-mark) + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)))) + ;; When source buffer and destination buffer are different, + ;; keep (set back the original text as region) or remove the + ;; original text. + (select-window window) ; Select window with source buffer. + (goto-char point) ; Move point to the original text on source buffer. + + (if mouse-drag-and-drop-region-cut-when-buffers-differ + ;; Remove the dragged text from source buffer like + ;; operation `cut'. + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)) + ;; Set back the dragged text as region on source buffer + ;; like operation `copy'. + (activate-mark)) + (select-window window-to-paste)))))) + + ;; Clean up. + (delete-overlay mouse-drag-and-drop-overlay) + + ;; Restore old states but for the window where the drop + ;; occurred. Restore cursor types for all windows. + (dolist (state states) + (let ((window (car state))) + (when (and window-exempt + (not (eq window window-exempt))) + (set-window-start window (nth 1 state) 'noforce) + (set-marker (nth 1 state) nil) + ;; If window is selected, the following automatically sets + ;; point for that window's buffer. + (set-window-point window (nth 2 state)) + (set-marker (nth 2 state) nil)) + (with-current-buffer (window-buffer window) + (setq cursor-type (nth 3 state))))))) \f ;;; Bindings for mouse commands. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-15 8:50 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-15 13:25 ` martin rudalics 2017-12-16 2:07 ` mouse-drag-and-drop-region Tak Kunihiro 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-12-15 13:25 UTC (permalink / raw) To: Tak Kunihiro; +Cc: Eli Zaretskii, rswgnu, Alex, emacs-devel [-- Attachment #1: Type: text/plain, Size: 418 bytes --] > Thanks. I resend you yet another revised version which mostly fixes the > doc-strings of these options and replaces the option > `mouse-drag-and-drop-region-face' with a face > `mouse-drag-and-drop-region' inheriting from the region face. Please > have a look. Unless you or someone else sees problems, I will install > it. The version I attached had a silly bug. Please use the one I attach now. martin [-- Attachment #2: mouse.el.diff --] [-- Type: text/plain, Size: 17245 bytes --] diff --git a/lisp/mouse.el b/lisp/mouse.el index 17d1732..ea8cf78 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -2345,10 +2345,10 @@ mouse-appearance-menu \f ;; Drag and drop support. (defcustom mouse-drag-and-drop-region nil - "If non-nil, dragging the mouse drags the region, if that exists. -If the value is a modifier, such as `control' or `shift' or `meta', -then if that modifier key is pressed when dropping the region, region -text is copied instead of being cut." + "If non-nil, dragging the mouse drags the region, if it exists. +If the value is a modifier, such as `control' or `shift' or +`meta', then if that modifier key is pressed when dropping the +region, text is copied instead of being cut." :type `(choice (const :tag "Disable dragging the region" nil) ,@(mapcar @@ -2361,6 +2361,45 @@ mouse-drag-and-drop-region :version "26.1" :group 'mouse) +(defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil + "If non-nil, cut text also when source and destination buffers differ. +If this option is nil, `mouse-drag-and-drop-region' will leave +the text in the source buffer alone when dropping it in a +different buffer. If this is non-nil, it will cut the text just +as it does when dropping text in the source buffer." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-tooltip 256 + "If non-nil, text is shown by a tooltip in a graphic display. +If this option is nil, `mouse-drag-and-drop-region' does not show +tooltips. If this is t, it shows the entire text dragged in a +tooltip. If this is an integer (as with the default value of +256), it will show that many characters of the dragged text in +a tooltip." + :type 'integer + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-cursor t + "If non-nil, move point with mouse cursor during dragging. +If this is nil, `mouse-drag-and-drop-region' leaves point alone. +Otherwise, it will move point together with the mouse cursor and, +in addition, temporarily highlight the original region with the +`mouse-drag-and-drop-region' face." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defface mouse-drag-and-drop-region '((t :inherit region)) + "Face to highlight original text during dragging. +This face is used by `mouse-drag-and-drop-region' to temporarily +highlight the original region when +`mouse-drag-and-drop-region-show-cursor' is non-nil." + :version "26.1" + :group 'mouse) + (defun mouse-drag-and-drop-region (event) "Move text in the region to point where mouse is dragged to. The transportation of text is also referred as `drag and drop'. @@ -2369,66 +2408,248 @@ mouse-drag-and-drop-region variable `mouse-drag-and-drop-region' is that modifier, the text is copied instead of being cut." (interactive "e") - (require 'tooltip) - (let ((start (region-beginning)) - (end (region-end)) - (point (point)) - (buffer (current-buffer)) - (window (selected-window)) - value-selection) - (track-mouse - ;; When event was click instead of drag, skip loop - (while (progn - (setq event (read-event)) - (or (mouse-movement-p event) - ;; Handle `mouse-autoselect-window'. - (eq (car-safe event) 'select-window))) - (unless value-selection ; initialization - (delete-overlay mouse-secondary-overlay) - (setq value-selection (buffer-substring start end)) - (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) - (ignore-errors (deactivate-mark) ; care existing region in other window - (mouse-set-point event) - (tooltip-show value-selection))) - (tooltip-hide)) - ;; Do not modify buffer under mouse when "event was click", - ;; "drag negligible", or - ;; "drag to read-only". - (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" - (member 'secondary-selection ; "drag negligible" - (mapcar (lambda (xxx) (overlay-get xxx 'face)) - (overlays-at (posn-point (event-end event))))) - buffer-read-only) - ;; Do not modify buffer under mouse. + (let* ((mouse-button (event-basic-type last-input-event)) + (mouse-drag-and-drop-region-show-tooltip + (when (and mouse-drag-and-drop-region-show-tooltip + (display-multi-frame-p) + (require 'tooltip)) + mouse-drag-and-drop-region-show-tooltip)) + (start (region-beginning)) + (end (region-end)) + (point (point)) + (buffer (current-buffer)) + (window (selected-window)) + (text-from-read-only buffer-read-only) + (mouse-drag-and-drop-overlay (make-overlay start end)) + point-to-paste + point-to-paste-read-only + window-to-paste + buffer-to-paste + cursor-in-text-area + no-modifier-on-drop + drag-but-negligible + clicked + value-selection ; This remains nil when event was "click". + text-tooltip + states + window-exempt) + + ;; STATES stores for each window on this frame its start and point + ;; positions so we can restore them on all windows but for the one + ;; where the drop occurs. For inter-frame drags we'll have to do + ;; this for all windows on all visible frames. In addition we save + ;; also the cursor type for the window's buffer so we can restore it + ;; in case we modified it. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-12/msg00090.html + (walk-window-tree + (lambda (window) + (setq states + (cons + (list + window + (copy-marker (window-start window)) + (copy-marker (window-point window)) + (with-current-buffer (window-buffer window) + cursor-type)) + states)))) + + (ignore-errors + (track-mouse + ;; When event was "click" instead of "drag", skip loop. + (while (progn + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00364.html + (setq event (read-key)) ; read-event or read-key + (or (mouse-movement-p event) + ;; Handle `mouse-autoselect-window'. + (eq (car-safe event) 'select-window))) + ;; Obtain the dragged text in region. When the loop was + ;; skipped, value-selection remains nil. + (unless value-selection + (setq value-selection (buffer-substring start end)) + (when mouse-drag-and-drop-region-show-tooltip + (let ((text-size mouse-drag-and-drop-region-show-tooltip)) + (setq text-tooltip (if (and (integerp text-size) + (> (length value-selection) text-size)) + (concat + (substring value-selection 0 (/ text-size 2)) + "\n...\n" + (substring value-selection (- (/ text-size 2)) -1)) + value-selection)))) + + ;; Check if selected text is read-only. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00663.html + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq text-from-read-only (or text-from-read-only + (get-text-property start 'read-only) + (not (equal + (next-single-char-property-change start 'read-only nil end) + end))))) + (setq window-to-paste (posn-window (event-end event))) + (setq point-to-paste (posn-point (event-end event))) + (setq buffer-to-paste (let (buf) ; Set nil when target buffer is minibuffer. + (when (windowp window-to-paste) + (setq buf (window-buffer window-to-paste)) + (when (not (minibufferp buf)) + buf)))) + (setq cursor-in-text-area (and window-to-paste + point-to-paste + buffer-to-paste)) + + (when cursor-in-text-area + ;; Check if point under mouse is read-only. + (save-window-excursion + (select-window window-to-paste) + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq point-to-paste-read-only + (or buffer-read-only + (get-text-property point-to-paste 'read-only)))) + + ;; Check if "drag but negligible". Operation "drag but + ;; negligible" is defined as drag-and-drop the text to + ;; the original region. When modifier is pressed, the + ;; text will be inserted to inside of the original + ;; region. + (setq drag-but-negligible + (member mouse-drag-and-drop-region + (mapcar (lambda (xxx) (overlay-get xxx 'face)) + (overlays-at point-to-paste))))) + + ;; Show a tooltip. + (if mouse-drag-and-drop-region-show-tooltip + ;; (and mouse-drag-and-drop-region-show-tooltip + ;; (not drag-but-negligible) + ;; (not point-to-paste-read-only) + ;; cursor-in-text-area) + (tooltip-show text-tooltip) + (tooltip-hide)) + + ;; Show cursor and highlight the original region. + (when mouse-drag-and-drop-region-show-cursor + ;; Modify cursor even when point is out of frame. + (setq cursor-type (cond + ((not cursor-in-text-area) + nil) + ((or point-to-paste-read-only + drag-but-negligible) + 'hollow) + (t + 'bar))) + (when cursor-in-text-area + (overlay-put mouse-drag-and-drop-overlay + 'face 'mouse-drag-and-drop-region) + (deactivate-mark) ; Maintain region in other window. + (mouse-set-point event))))) + + ;; Hide a tooltip. + (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide)) + + ;; Check if modifier was pressed on drop. + (setq no-modifier-on-drop + (not (member mouse-drag-and-drop-region (event-modifiers event)))) + + ;; Check if event was "click". + (setq clicked (not value-selection)) + + ;; Restore status on drag to outside of text-area or non-mouse input. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00486.html + (when (or (not cursor-in-text-area) + (not (equal (event-basic-type event) mouse-button))) + (setq drag-but-negligible t + no-modifier-on-drop t)) + + ;; Do not modify any buffers when event is "click", + ;; "drag but negligible", or "drag to read-only". + (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ + (if no-modifier-on-drop + mouse-drag-and-drop-region-cut-when-buffers-differ + (not mouse-drag-and-drop-region-cut-when-buffers-differ))) + (wanna-paste-to-same-buffer (equal buffer-to-paste buffer)) + (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer + no-modifier-on-drop)) + (wanna-cut-on-other-buffer (and (not wanna-paste-to-same-buffer) + mouse-drag-and-drop-region-cut-when-buffers-differ)) + (cannot-paste (or point-to-paste-read-only + (when (or wanna-cut-on-same-buffer + wanna-cut-on-other-buffer) + text-from-read-only)))) + (cond - ;; "drag negligible" or "drag to read-only", restore region. - (value-selection - (select-window window) ; In case miss drag to other window + ;; Move point within region. + (clicked + (deactivate-mark) + (mouse-set-point event)) + ;; Undo operation. Set back the original text as region. + ((or (and drag-but-negligible + no-modifier-on-drop) + cannot-paste) + ;; Inform user either source or destination buffer cannot be modified. + (when (and (not drag-but-negligible) + cannot-paste) + (message "Buffer is read-only")) + + ;; Select source window back and restore region. + ;; (set-window-point window point) + (select-window window) (goto-char point) (setq deactivate-mark nil) (activate-mark)) - ;; "event was click" + ;; Modify buffers. (t - (deactivate-mark) - (mouse-set-point event))) - ;; Modify buffer under mouse by inserting text. - (push-mark) - (insert value-selection) - (when (not (equal (mark) (point))) ; on success insert - (setq deactivate-mark nil) - (activate-mark)) ; have region on destination - ;; Take care of initial region on source. - (if (equal (current-buffer) buffer) ; when same buffer - (let (deactivate-mark) ; remove text - (unless (member mouse-drag-and-drop-region (event-modifiers event)) - (kill-region (overlay-start mouse-secondary-overlay) - (overlay-end mouse-secondary-overlay)))) - (let ((window1 (selected-window))) ; when beyond buffer - (select-window window) - (goto-char point) ; restore point on source window - (activate-mark) ; restore region - (select-window window1)))) - (delete-overlay mouse-secondary-overlay))) + ;; * DESTINATION BUFFER:: + ;; Insert the text to destination buffer under mouse. + (select-window window-to-paste) + (setq window-exempt window-to-paste) + (goto-char point-to-paste) + (push-mark) + (insert value-selection) + ;; On success, set the text as region on destination buffer. + (when (not (equal (mark) (point))) + (setq deactivate-mark nil) + (activate-mark)) + + ;; * SOURCE BUFFER:: + ;; Set back the original text as region or delete the original + ;; text, on source buffer. + (if wanna-paste-to-same-buffer + ;; When source buffer and destination buffer are the same, + ;; remove the original text. + (when no-modifier-on-drop + (let (deactivate-mark) + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)))) + ;; When source buffer and destination buffer are different, + ;; keep (set back the original text as region) or remove the + ;; original text. + (select-window window) ; Select window with source buffer. + (goto-char point) ; Move point to the original text on source buffer. + + (if mouse-drag-and-drop-region-cut-when-buffers-differ + ;; Remove the dragged text from source buffer like + ;; operation `cut'. + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)) + ;; Set back the dragged text as region on source buffer + ;; like operation `copy'. + (activate-mark)) + (select-window window-to-paste)))))) + + ;; Clean up. + (delete-overlay mouse-drag-and-drop-overlay) + + ;; Restore old states but for the window where the drop + ;; occurred. Restore cursor types for all windows. + (dolist (state states) + (let ((window (car state))) + (when (and window-exempt + (not (eq window window-exempt))) + (set-window-start window (nth 1 state) 'noforce) + (set-marker (nth 1 state) nil) + ;; If window is selected, the following automatically sets + ;; point for that window's buffer. + (set-window-point window (nth 2 state)) + (set-marker (nth 2 state) nil)) + (with-current-buffer (window-buffer window) + (setq cursor-type (nth 3 state))))))) \f ;;; Bindings for mouse commands. ^ permalink raw reply related [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-15 13:25 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-16 2:07 ` Tak Kunihiro 2017-12-16 9:42 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Tak Kunihiro @ 2017-12-16 2:07 UTC (permalink / raw) To: rudalics; +Cc: tkk, eliz, rswgnu, agrambot, emacs-devel >> option `mouse-drag-and-drop-region-face' with a face >> `mouse-drag-and-drop-region' inheriting from the region face. During the drag, when mouse point is on the original region, cursor would be set to hollow. With this revision, I see that the cursor is not set. To do it, drag-but-negligible should be set to t. The drag-but-negligible is set by following expressions. 2507 ;; Check if "drag but negligible". Operation "drag but 2508 ;; negligible" is defined as drag-and-drop the text to 2509 ;; the original region. When modifier is pressed, the 2510 ;; text will be inserted to inside of the original 2511 ;; region. 2512 (setq drag-but-negligible 2513 (member mouse-drag-and-drop-region 2514 (mapcar (lambda (xxx) (overlay-get xxx 'face)) 2515 (overlays-at point-to-paste))))) On this revision, I wonder if mouse-drag-and-drop-region on line 2513 refers to variable instead of face. No? ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-16 2:07 ` mouse-drag-and-drop-region Tak Kunihiro @ 2017-12-16 9:42 ` martin rudalics 2017-12-17 4:40 ` mouse-drag-and-drop-region Tak Kunihiro 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-12-16 9:42 UTC (permalink / raw) To: Tak Kunihiro; +Cc: eliz, rswgnu, agrambot, emacs-devel [-- Attachment #1: Type: text/plain, Size: 1755 bytes --] > During the drag, when mouse point is on the original region, cursor > would be set to hollow. With this revision, I see that the cursor is > not set. Right. > To do it, drag-but-negligible should be set to t. The > drag-but-negligible is set by following expressions. > > 2507 ;; Check if "drag but negligible". Operation "drag but > 2508 ;; negligible" is defined as drag-and-drop the text to > 2509 ;; the original region. When modifier is pressed, the > 2510 ;; text will be inserted to inside of the original > 2511 ;; region. > 2512 (setq drag-but-negligible > 2513 (member mouse-drag-and-drop-region > 2514 (mapcar (lambda (xxx) (overlay-get xxx 'face)) > 2515 (overlays-at point-to-paste))))) > > On this revision, I wonder if mouse-drag-and-drop-region on line 2513 > refers to variable instead of face. No? Right again. What about directly checking the overlay boundaries instead as in the attached patch which appears cleaner than to rely on face properties? Note that this way a user can also insert the text immediately before the original region which IIUC is not possible with the original behavior. Maybe we should also call the face `mouse-drag-and-drop-highlight' so that there is less confusion. OT1H faces should not end with the postfix "-face" and OTOH the simple variable you used initially had a user rely on predefined faces only which is an unnecessary restriction. Some users might dislike `region' and `secondary-selection' here. And please go over the entire text once again so that lines are no more longer than 80 characters at most (I already tried that in some cases). Thanks, martin [-- Attachment #2: mouse.el.diff --] [-- Type: text/plain, Size: 17273 bytes --] diff --git a/lisp/mouse.el b/lisp/mouse.el index 17d1732..e90eada 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -2345,10 +2345,10 @@ mouse-appearance-menu \f ;; Drag and drop support. (defcustom mouse-drag-and-drop-region nil - "If non-nil, dragging the mouse drags the region, if that exists. -If the value is a modifier, such as `control' or `shift' or `meta', -then if that modifier key is pressed when dropping the region, region -text is copied instead of being cut." + "If non-nil, dragging the mouse drags the region, if it exists. +If the value is a modifier, such as `control' or `shift' or +`meta', then if that modifier key is pressed when dropping the +region, text is copied instead of being cut." :type `(choice (const :tag "Disable dragging the region" nil) ,@(mapcar @@ -2361,6 +2361,45 @@ mouse-drag-and-drop-region :version "26.1" :group 'mouse) +(defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil + "If non-nil, cut text also when source and destination buffers differ. +If this option is nil, `mouse-drag-and-drop-region' will leave +the text in the source buffer alone when dropping it in a +different buffer. If this is non-nil, it will cut the text just +as it does when dropping text in the source buffer." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-tooltip 256 + "If non-nil, text is shown by a tooltip in a graphic display. +If this option is nil, `mouse-drag-and-drop-region' does not show +tooltips. If this is t, it shows the entire text dragged in a +tooltip. If this is an integer (as with the default value of +256), it will show that many characters of the dragged text in +a tooltip." + :type 'integer + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-cursor t + "If non-nil, move point with mouse cursor during dragging. +If this is nil, `mouse-drag-and-drop-region' leaves point alone. +Otherwise, it will move point together with the mouse cursor and, +in addition, temporarily highlight the original region with the +`mouse-drag-and-drop-region' face." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defface mouse-drag-and-drop-region '((t :inherit region)) + "Face to highlight original text during dragging. +This face is used by `mouse-drag-and-drop-region' to temporarily +highlight the original region when +`mouse-drag-and-drop-region-show-cursor' is non-nil." + :version "26.1" + :group 'mouse) + (defun mouse-drag-and-drop-region (event) "Move text in the region to point where mouse is dragged to. The transportation of text is also referred as `drag and drop'. @@ -2369,66 +2408,251 @@ mouse-drag-and-drop-region variable `mouse-drag-and-drop-region' is that modifier, the text is copied instead of being cut." (interactive "e") - (require 'tooltip) - (let ((start (region-beginning)) - (end (region-end)) - (point (point)) - (buffer (current-buffer)) - (window (selected-window)) - value-selection) - (track-mouse - ;; When event was click instead of drag, skip loop - (while (progn - (setq event (read-event)) - (or (mouse-movement-p event) - ;; Handle `mouse-autoselect-window'. - (eq (car-safe event) 'select-window))) - (unless value-selection ; initialization - (delete-overlay mouse-secondary-overlay) - (setq value-selection (buffer-substring start end)) - (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) - (ignore-errors (deactivate-mark) ; care existing region in other window - (mouse-set-point event) - (tooltip-show value-selection))) - (tooltip-hide)) - ;; Do not modify buffer under mouse when "event was click", - ;; "drag negligible", or - ;; "drag to read-only". - (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" - (member 'secondary-selection ; "drag negligible" - (mapcar (lambda (xxx) (overlay-get xxx 'face)) - (overlays-at (posn-point (event-end event))))) - buffer-read-only) - ;; Do not modify buffer under mouse. + (let* ((mouse-button (event-basic-type last-input-event)) + (mouse-drag-and-drop-region-show-tooltip + (when (and mouse-drag-and-drop-region-show-tooltip + (display-multi-frame-p) + (require 'tooltip)) + mouse-drag-and-drop-region-show-tooltip)) + (start (region-beginning)) + (end (region-end)) + (point (point)) + (buffer (current-buffer)) + (window (selected-window)) + (text-from-read-only buffer-read-only) + (mouse-drag-and-drop-overlay (make-overlay start end)) + point-to-paste + point-to-paste-read-only + window-to-paste + buffer-to-paste + cursor-in-text-area + no-modifier-on-drop + drag-but-negligible + clicked + value-selection ; This remains nil when event was "click". + text-tooltip + states + window-exempt) + + ;; STATES stores for each window on this frame its start and point + ;; positions so we can restore them on all windows but for the one + ;; where the drop occurs. For inter-frame drags we'll have to do + ;; this for all windows on all visible frames. In addition we save + ;; also the cursor type for the window's buffer so we can restore it + ;; in case we modified it. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-12/msg00090.html + (walk-window-tree + (lambda (window) + (setq states + (cons + (list + window + (copy-marker (window-start window)) + (copy-marker (window-point window)) + (with-current-buffer (window-buffer window) + cursor-type)) + states)))) + + (ignore-errors + (track-mouse + ;; When event was "click" instead of "drag", skip loop. + (while (progn + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00364.html + (setq event (read-key)) ; read-event or read-key + (or (mouse-movement-p event) + ;; Handle `mouse-autoselect-window'. + (eq (car-safe event) 'select-window))) + ;; Obtain the dragged text in region. When the loop was + ;; skipped, value-selection remains nil. + (unless value-selection + (setq value-selection (buffer-substring start end)) + (when mouse-drag-and-drop-region-show-tooltip + (let ((text-size mouse-drag-and-drop-region-show-tooltip)) + (setq text-tooltip + (if (and (integerp text-size) + (> (length value-selection) text-size)) + (concat + (substring value-selection 0 (/ text-size 2)) + "\n...\n" + (substring value-selection (- (/ text-size 2)) -1)) + value-selection)))) + + ;; Check if selected text is read-only. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00663.html + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq text-from-read-only (or text-from-read-only + (get-text-property start 'read-only) + (not (equal + (next-single-char-property-change + start 'read-only nil end) + end))))) + (setq window-to-paste (posn-window (event-end event))) + (setq point-to-paste (posn-point (event-end event))) + (setq buffer-to-paste (let (buf) ; Set nil when target buffer is minibuffer. + (when (windowp window-to-paste) + (setq buf (window-buffer window-to-paste)) + (when (not (minibufferp buf)) + buf)))) + (setq cursor-in-text-area (and window-to-paste + point-to-paste + buffer-to-paste)) + + (when cursor-in-text-area + ;; Check if point under mouse is read-only. + (save-window-excursion + (select-window window-to-paste) + ;; (add-text-properties (region-beginning) (region-end) '(read-only t)) + (setq point-to-paste-read-only + (or buffer-read-only + (get-text-property point-to-paste 'read-only)))) + + ;; Check if "drag but negligible". Operation "drag but + ;; negligible" is defined as drag-and-drop the text to + ;; the original region. When modifier is pressed, the + ;; text will be inserted to inside of the original + ;; region. + (setq drag-but-negligible + (and (< (overlay-start mouse-drag-and-drop-overlay) + point-to-paste) + (< point-to-paste + (overlay-end mouse-drag-and-drop-overlay))))) + + ;; Show a tooltip. + (if mouse-drag-and-drop-region-show-tooltip + ;; (and mouse-drag-and-drop-region-show-tooltip + ;; (not drag-but-negligible) + ;; (not point-to-paste-read-only) + ;; cursor-in-text-area) + (tooltip-show text-tooltip) + (tooltip-hide)) + + ;; Show cursor and highlight the original region. + (when mouse-drag-and-drop-region-show-cursor + ;; Modify cursor even when point is out of frame. + (setq cursor-type (cond + ((not cursor-in-text-area) + nil) + ((or point-to-paste-read-only + drag-but-negligible) + 'hollow) + (t + 'bar))) + (when cursor-in-text-area + (overlay-put mouse-drag-and-drop-overlay + 'face 'mouse-drag-and-drop-region) + (deactivate-mark) ; Maintain region in other window. + (mouse-set-point event))))) + + ;; Hide a tooltip. + (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide)) + + ;; Check if modifier was pressed on drop. + (setq no-modifier-on-drop + (not (member mouse-drag-and-drop-region (event-modifiers event)))) + + ;; Check if event was "click". + (setq clicked (not value-selection)) + + ;; Restore status on drag to outside of text-area or non-mouse input. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00486.html + (when (or (not cursor-in-text-area) + (not (equal (event-basic-type event) mouse-button))) + (setq drag-but-negligible t + no-modifier-on-drop t)) + + ;; Do not modify any buffers when event is "click", + ;; "drag but negligible", or "drag to read-only". + (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ + (if no-modifier-on-drop + mouse-drag-and-drop-region-cut-when-buffers-differ + (not mouse-drag-and-drop-region-cut-when-buffers-differ))) + (wanna-paste-to-same-buffer (equal buffer-to-paste buffer)) + (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer + no-modifier-on-drop)) + (wanna-cut-on-other-buffer (and (not wanna-paste-to-same-buffer) + mouse-drag-and-drop-region-cut-when-buffers-differ)) + (cannot-paste (or point-to-paste-read-only + (when (or wanna-cut-on-same-buffer + wanna-cut-on-other-buffer) + text-from-read-only)))) + (cond - ;; "drag negligible" or "drag to read-only", restore region. - (value-selection - (select-window window) ; In case miss drag to other window + ;; Move point within region. + (clicked + (deactivate-mark) + (mouse-set-point event)) + ;; Undo operation. Set back the original text as region. + ((or (and drag-but-negligible + no-modifier-on-drop) + cannot-paste) + ;; Inform user either source or destination buffer cannot be modified. + (when (and (not drag-but-negligible) + cannot-paste) + (message "Buffer is read-only")) + + ;; Select source window back and restore region. + ;; (set-window-point window point) + (select-window window) (goto-char point) (setq deactivate-mark nil) (activate-mark)) - ;; "event was click" + ;; Modify buffers. (t - (deactivate-mark) - (mouse-set-point event))) - ;; Modify buffer under mouse by inserting text. - (push-mark) - (insert value-selection) - (when (not (equal (mark) (point))) ; on success insert - (setq deactivate-mark nil) - (activate-mark)) ; have region on destination - ;; Take care of initial region on source. - (if (equal (current-buffer) buffer) ; when same buffer - (let (deactivate-mark) ; remove text - (unless (member mouse-drag-and-drop-region (event-modifiers event)) - (kill-region (overlay-start mouse-secondary-overlay) - (overlay-end mouse-secondary-overlay)))) - (let ((window1 (selected-window))) ; when beyond buffer - (select-window window) - (goto-char point) ; restore point on source window - (activate-mark) ; restore region - (select-window window1)))) - (delete-overlay mouse-secondary-overlay))) + ;; * DESTINATION BUFFER:: + ;; Insert the text to destination buffer under mouse. + (select-window window-to-paste) + (setq window-exempt window-to-paste) + (goto-char point-to-paste) + (push-mark) + (insert value-selection) + ;; On success, set the text as region on destination buffer. + (when (not (equal (mark) (point))) + (setq deactivate-mark nil) + (activate-mark)) + + ;; * SOURCE BUFFER:: + ;; Set back the original text as region or delete the original + ;; text, on source buffer. + (if wanna-paste-to-same-buffer + ;; When source buffer and destination buffer are the same, + ;; remove the original text. + (when no-modifier-on-drop + (let (deactivate-mark) + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)))) + ;; When source buffer and destination buffer are different, + ;; keep (set back the original text as region) or remove the + ;; original text. + (select-window window) ; Select window with source buffer. + (goto-char point) ; Move point to the original text on source buffer. + + (if mouse-drag-and-drop-region-cut-when-buffers-differ + ;; Remove the dragged text from source buffer like + ;; operation `cut'. + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)) + ;; Set back the dragged text as region on source buffer + ;; like operation `copy'. + (activate-mark)) + (select-window window-to-paste)))))) + + ;; Clean up. + (delete-overlay mouse-drag-and-drop-overlay) + + ;; Restore old states but for the window where the drop + ;; occurred. Restore cursor types for all windows. + (dolist (state states) + (let ((window (car state))) + (when (and window-exempt + (not (eq window window-exempt))) + (set-window-start window (nth 1 state) 'noforce) + (set-marker (nth 1 state) nil) + ;; If window is selected, the following automatically sets + ;; point for that window's buffer. + (set-window-point window (nth 2 state)) + (set-marker (nth 2 state) nil)) + (with-current-buffer (window-buffer window) + (setq cursor-type (nth 3 state))))))) \f ;;; Bindings for mouse commands. ^ permalink raw reply related [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-16 9:42 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-17 4:40 ` Tak Kunihiro 2017-12-17 10:44 ` mouse-drag-and-drop-region martin rudalics 0 siblings, 1 reply; 89+ messages in thread From: Tak Kunihiro @ 2017-12-17 4:40 UTC (permalink / raw) To: rudalics; +Cc: tkk, eliz, rswgnu, agrambot, emacs-devel [-- Attachment #1: Type: Text/Plain, Size: 1624 bytes --] Thank you for the response. > What about directly checking the overlay boundaries instead as in > the attached patch which appears cleaner than to rely on face > properties? I think that is good. > Maybe we should also call the face `mouse-drag-and-drop-highlight' > so that there is less confusion. OT1H faces should not end with the > postfix "-face" and OTOH the simple variable you used initially had > a user rely on predefined faces only which is an unnecessary > restriction. Some users might dislike `region' and > `secondary-selection' here. There already are function `mouse-drag-and-drop' and variable `mouse-drag-and-drop'. Thus I think there is no problem to have face `mouse-drag-and-drop'. > And please go over the entire text once again so that lines are no > more longer than 80 characters at most. I take out several comments to make lines no more longer than 80 characters. I'm sending ChangeLog, and patch. * ChangeLog 2017-12-17 Tak Kunihiro <tkk@misasa.okayama-u.ac.jp> Improve comments and have new options * lisp/mouse.el (mouse-drag-and-drop-region): Have options to make dragging cut among buffers. Make usage of tooltip option. (mouse-drag-and-drop-region-cut-when-buffers-differ): New variable. If non-nil, cut text also when source and destination buffers differ. (mouse-drag-and-drop-region-show-tooltip): New variable. If non-nil, text is shown by a tooltip in a graphic display. (mouse-drag-and-drop-region-show-cursor): New variable. If non-nil, move point with mouse cursor during dragging. (mouse-drag-and-drop-region): New face to highlight original text during dragging. [-- Attachment #2: mouse.el.diff --] [-- Type: Text/X-Patch, Size: 16669 bytes --] diff --git a/lisp/mouse.el b/lisp/mouse.el index 17d1732..d326202 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -2345,10 +2345,10 @@ choose a font." \f ;; Drag and drop support. (defcustom mouse-drag-and-drop-region nil - "If non-nil, dragging the mouse drags the region, if that exists. -If the value is a modifier, such as `control' or `shift' or `meta', -then if that modifier key is pressed when dropping the region, region -text is copied instead of being cut." + "If non-nil, dragging the mouse drags the region, if it exists. +If the value is a modifier, such as `control' or `shift' or +`meta', then if that modifier key is pressed when dropping the +region, text is copied instead of being cut." :type `(choice (const :tag "Disable dragging the region" nil) ,@(mapcar @@ -2361,6 +2361,45 @@ text is copied instead of being cut." :version "26.1" :group 'mouse) +(defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil + "If non-nil, cut text also when source and destination buffers differ. +If this option is nil, `mouse-drag-and-drop-region' will leave +the text in the source buffer alone when dropping it in a +different buffer. If this is non-nil, it will cut the text just +as it does when dropping text in the source buffer." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-tooltip 256 + "If non-nil, text is shown by a tooltip in a graphic display. +If this option is nil, `mouse-drag-and-drop-region' does not show +tooltips. If this is t, it shows the entire text dragged in a +tooltip. If this is an integer (as with the default value of +256), it will show that many characters of the dragged text in +a tooltip." + :type 'integer + :version "26.1" + :group 'mouse) + +(defcustom mouse-drag-and-drop-region-show-cursor t + "If non-nil, move point with mouse cursor during dragging. +If this is nil, `mouse-drag-and-drop-region' leaves point alone. +Otherwise, it will move point together with the mouse cursor and, +in addition, temporarily highlight the original region with the +`mouse-drag-and-drop-region' face." + :type 'boolean + :version "26.1" + :group 'mouse) + +(defface mouse-drag-and-drop-region '((t :inherit region)) + "Face to highlight original text during dragging. +This face is used by `mouse-drag-and-drop-region' to temporarily +highlight the original region when +`mouse-drag-and-drop-region-show-cursor' is non-nil." + :version "26.1" + :group 'mouse) + (defun mouse-drag-and-drop-region (event) "Move text in the region to point where mouse is dragged to. The transportation of text is also referred as `drag and drop'. @@ -2369,66 +2408,244 @@ modifier key was pressed when dropping, and the value of the variable `mouse-drag-and-drop-region' is that modifier, the text is copied instead of being cut." (interactive "e") - (require 'tooltip) - (let ((start (region-beginning)) - (end (region-end)) - (point (point)) - (buffer (current-buffer)) - (window (selected-window)) - value-selection) - (track-mouse - ;; When event was click instead of drag, skip loop - (while (progn - (setq event (read-event)) - (or (mouse-movement-p event) - ;; Handle `mouse-autoselect-window'. - (eq (car-safe event) 'select-window))) - (unless value-selection ; initialization - (delete-overlay mouse-secondary-overlay) - (setq value-selection (buffer-substring start end)) - (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark) - (ignore-errors (deactivate-mark) ; care existing region in other window - (mouse-set-point event) - (tooltip-show value-selection))) - (tooltip-hide)) - ;; Do not modify buffer under mouse when "event was click", - ;; "drag negligible", or - ;; "drag to read-only". - (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click" - (member 'secondary-selection ; "drag negligible" - (mapcar (lambda (xxx) (overlay-get xxx 'face)) - (overlays-at (posn-point (event-end event))))) - buffer-read-only) - ;; Do not modify buffer under mouse. + (let* ((mouse-button (event-basic-type last-input-event)) + (mouse-drag-and-drop-region-show-tooltip + (when (and mouse-drag-and-drop-region-show-tooltip + (display-multi-frame-p) + (require 'tooltip)) + mouse-drag-and-drop-region-show-tooltip)) + (start (region-beginning)) + (end (region-end)) + (point (point)) + (buffer (current-buffer)) + (window (selected-window)) + (text-from-read-only buffer-read-only) + (mouse-drag-and-drop-overlay (make-overlay start end)) + point-to-paste + point-to-paste-read-only + window-to-paste + buffer-to-paste + cursor-in-text-area + no-modifier-on-drop + drag-but-negligible + clicked + value-selection ; This remains nil when event was "click". + text-tooltip + states + window-exempt) + + ;; STATES stores for each window on this frame its start and point + ;; positions so we can restore them on all windows but for the one + ;; where the drop occurs. For inter-frame drags we'll have to do + ;; this for all windows on all visible frames. In addition we save + ;; also the cursor type for the window's buffer so we can restore it + ;; in case we modified it. + ;; https://lists.gnu.org/archive/html/emacs-devel/2017-12/msg00090.html + (walk-window-tree + (lambda (window) + (setq states + (cons + (list + window + (copy-marker (window-start window)) + (copy-marker (window-point window)) + (with-current-buffer (window-buffer window) + cursor-type)) + states)))) + + (ignore-errors + (track-mouse + ;; When event was "click" instead of "drag", skip loop. + (while (progn + (setq event (read-key)) ; read-event or read-key + (or (mouse-movement-p event) + ;; Handle `mouse-autoselect-window'. + (eq (car-safe event) 'select-window))) + ;; Obtain the dragged text in region. When the loop was + ;; skipped, value-selection remains nil. + (unless value-selection + (setq value-selection (buffer-substring start end)) + (when mouse-drag-and-drop-region-show-tooltip + (let ((text-size mouse-drag-and-drop-region-show-tooltip)) + (setq text-tooltip + (if (and (integerp text-size) + (> (length value-selection) text-size)) + (concat + (substring value-selection 0 (/ text-size 2)) + "\n...\n" + (substring value-selection (- (/ text-size 2)) -1)) + value-selection)))) + + ;; Check if selected text is read-only. + (setq text-from-read-only (or text-from-read-only + (get-text-property start 'read-only) + (not (equal + (next-single-char-property-change + start 'read-only nil end) + end))))) + (setq window-to-paste (posn-window (event-end event))) + (setq point-to-paste (posn-point (event-end event))) + ;; Set nil when target buffer is minibuffer. + (setq buffer-to-paste (let (buf) + (when (windowp window-to-paste) + (setq buf (window-buffer window-to-paste)) + (when (not (minibufferp buf)) + buf)))) + (setq cursor-in-text-area (and window-to-paste + point-to-paste + buffer-to-paste)) + + (when cursor-in-text-area + ;; Check if point under mouse is read-only. + (save-window-excursion + (select-window window-to-paste) + (setq point-to-paste-read-only + (or buffer-read-only + (get-text-property point-to-paste 'read-only)))) + + ;; Check if "drag but negligible". Operation "drag but + ;; negligible" is defined as drag-and-drop the text to + ;; the original region. When modifier is pressed, the + ;; text will be inserted to inside of the original + ;; region. + (setq drag-but-negligible + (and (< (overlay-start mouse-drag-and-drop-overlay) + point-to-paste) + (< point-to-paste + (overlay-end mouse-drag-and-drop-overlay))))) + + ;; Show a tooltip. + (if mouse-drag-and-drop-region-show-tooltip + (tooltip-show text-tooltip) + (tooltip-hide)) + + ;; Show cursor and highlight the original region. + (when mouse-drag-and-drop-region-show-cursor + ;; Modify cursor even when point is out of frame. + (setq cursor-type (cond + ((not cursor-in-text-area) + nil) + ((or point-to-paste-read-only + drag-but-negligible) + 'hollow) + (t + 'bar))) + (when cursor-in-text-area + (overlay-put mouse-drag-and-drop-overlay + 'face 'mouse-drag-and-drop-region) + (deactivate-mark) ; Maintain region in other window. + (mouse-set-point event))))) + + ;; Hide a tooltip. + (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide)) + + ;; Check if modifier was pressed on drop. + (setq no-modifier-on-drop + (not (member mouse-drag-and-drop-region (event-modifiers event)))) + + ;; Check if event was "click". + (setq clicked (not value-selection)) + + ;; Restore status on drag to outside of text-area or non-mouse input. + (when (or (not cursor-in-text-area) + (not (equal (event-basic-type event) mouse-button))) + (setq drag-but-negligible t + no-modifier-on-drop t)) + + ;; Do not modify any buffers when event is "click", + ;; "drag but negligible", or "drag to read-only". + (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ + (if no-modifier-on-drop + mouse-drag-and-drop-region-cut-when-buffers-differ + (not mouse-drag-and-drop-region-cut-when-buffers-differ))) + (wanna-paste-to-same-buffer (equal buffer-to-paste buffer)) + (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer + no-modifier-on-drop)) + (wanna-cut-on-other-buffer + (and (not wanna-paste-to-same-buffer) + mouse-drag-and-drop-region-cut-when-buffers-differ)) + (cannot-paste (or point-to-paste-read-only + (when (or wanna-cut-on-same-buffer + wanna-cut-on-other-buffer) + text-from-read-only)))) + (cond - ;; "drag negligible" or "drag to read-only", restore region. - (value-selection - (select-window window) ; In case miss drag to other window + ;; Move point within region. + (clicked + (deactivate-mark) + (mouse-set-point event)) + ;; Undo operation. Set back the original text as region. + ((or (and drag-but-negligible + no-modifier-on-drop) + cannot-paste) + ;; Inform user either source or destination buffer cannot be modified. + (when (and (not drag-but-negligible) + cannot-paste) + (message "Buffer is read-only")) + + ;; Select source window back and restore region. + ;; (set-window-point window point) + (select-window window) (goto-char point) (setq deactivate-mark nil) (activate-mark)) - ;; "event was click" + ;; Modify buffers. (t - (deactivate-mark) - (mouse-set-point event))) - ;; Modify buffer under mouse by inserting text. - (push-mark) - (insert value-selection) - (when (not (equal (mark) (point))) ; on success insert - (setq deactivate-mark nil) - (activate-mark)) ; have region on destination - ;; Take care of initial region on source. - (if (equal (current-buffer) buffer) ; when same buffer - (let (deactivate-mark) ; remove text - (unless (member mouse-drag-and-drop-region (event-modifiers event)) - (kill-region (overlay-start mouse-secondary-overlay) - (overlay-end mouse-secondary-overlay)))) - (let ((window1 (selected-window))) ; when beyond buffer - (select-window window) - (goto-char point) ; restore point on source window - (activate-mark) ; restore region - (select-window window1)))) - (delete-overlay mouse-secondary-overlay))) + ;; * DESTINATION BUFFER:: + ;; Insert the text to destination buffer under mouse. + (select-window window-to-paste) + (setq window-exempt window-to-paste) + (goto-char point-to-paste) + (push-mark) + (insert value-selection) + ;; On success, set the text as region on destination buffer. + (when (not (equal (mark) (point))) + (setq deactivate-mark nil) + (activate-mark)) + + ;; * SOURCE BUFFER:: + ;; Set back the original text as region or delete the original + ;; text, on source buffer. + (if wanna-paste-to-same-buffer + ;; When source buffer and destination buffer are the same, + ;; remove the original text. + (when no-modifier-on-drop + (let (deactivate-mark) + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)))) + ;; When source buffer and destination buffer are different, + ;; keep (set back the original text as region) or remove the + ;; original text. + (select-window window) ; Select window with source buffer. + (goto-char point) ; Move point to the original text on source buffer. + + (if mouse-drag-and-drop-region-cut-when-buffers-differ + ;; Remove the dragged text from source buffer like + ;; operation `cut'. + (delete-region (overlay-start mouse-drag-and-drop-overlay) + (overlay-end mouse-drag-and-drop-overlay)) + ;; Set back the dragged text as region on source buffer + ;; like operation `copy'. + (activate-mark)) + (select-window window-to-paste)))))) + + ;; Clean up. + (delete-overlay mouse-drag-and-drop-overlay) + + ;; Restore old states but for the window where the drop + ;; occurred. Restore cursor types for all windows. + (dolist (state states) + (let ((window (car state))) + (when (and window-exempt + (not (eq window window-exempt))) + (set-window-start window (nth 1 state) 'noforce) + (set-marker (nth 1 state) nil) + ;; If window is selected, the following automatically sets + ;; point for that window's buffer. + (set-window-point window (nth 2 state)) + (set-marker (nth 2 state) nil)) + (with-current-buffer (window-buffer window) + (setq cursor-type (nth 3 state))))))) \f ;;; Bindings for mouse commands. ^ permalink raw reply related [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-17 4:40 ` mouse-drag-and-drop-region Tak Kunihiro @ 2017-12-17 10:44 ` martin rudalics 2017-12-21 1:36 ` mouse-drag-and-drop-region Tak Kunihiro 0 siblings, 1 reply; 89+ messages in thread From: martin rudalics @ 2017-12-17 10:44 UTC (permalink / raw) To: Tak Kunihiro; +Cc: eliz, rswgnu, agrambot, emacs-devel > I take out several comments to make lines no more longer than 80 > characters. > > I'm sending ChangeLog, and patch. I pushed it now with slight changes in the ChangeLog entry and one change in my earlier calculation of `drag-but-negligible' to avoid that a drop is rejected when source and destination buffer differ but the position in the destination buffer is a position in the original region of the source buffer. Please have a look. I believe the following calculations ... (if (and (integerp text-size) (> (length value-selection) text-size)) (concat (substring value-selection 0 (/ text-size 2)) "\n...\n" (substring value-selection (- (/ text-size 2)) -1)) value-selection)))) ... could be improved when the user has chosen a very small value for 'mouse-drag-and-drop-region-show-tooltip' but I have no good idea how to do that. Maybe also a value of zero should be handled like nil. But there's no great need for doing that. So let's see if there are any complaints. And maybe it's time to write some documentation now ... Thanks, martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-17 10:44 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-21 1:36 ` Tak Kunihiro 2017-12-22 8:43 ` mouse-drag-and-drop-region martin rudalics 2017-12-22 9:25 ` mouse-drag-and-drop-region Eli Zaretskii 0 siblings, 2 replies; 89+ messages in thread From: Tak Kunihiro @ 2017-12-21 1:36 UTC (permalink / raw) To: rudalics; +Cc: tkk, eliz, rswgnu, agrambot, emacs-devel [-- Attachment #1: Type: Text/Plain, Size: 116 bytes --] Thank you for the response. > it's time to write some documentation now ... Here I attach draft of documentation. [-- Attachment #2: frames.texi.diff --] [-- Type: Text/X-Patch, Size: 938 bytes --] diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index c94d690cf7..110199304e 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -1106,6 +1106,14 @@ then pressing that modifier key when dropping the text will copy it instead of cutting it, even if you drop on the same buffer as the one from which the text came. +If you want to cut text even when source and destination buffers +differ, set variable +@code{mouse-drag-and-drop-region-cut-when-buffers-differ} to non-nil. +If you do not want to see selected text in a tooltip in a graphic +display and/or move point together with the mouse cursor during +dragging, set @code{mouse-drag-and-drop-region-show-tooltip} and/or +@code{mouse-drag-and-drop-region-show-cursor} to nil. + @vindex dnd-open-file-other-window Dropping a file normally visits it in the window you drop it on. If you prefer to visit the file in a new window in such cases, customize ^ permalink raw reply related [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-21 1:36 ` mouse-drag-and-drop-region Tak Kunihiro @ 2017-12-22 8:43 ` martin rudalics 2017-12-22 9:25 ` mouse-drag-and-drop-region Eli Zaretskii 1 sibling, 0 replies; 89+ messages in thread From: martin rudalics @ 2017-12-22 8:43 UTC (permalink / raw) To: Tak Kunihiro; +Cc: eliz, rswgnu, agrambot, emacs-devel > Here I attach draft of documentation. Installed with modifications and also updated the NEWS entry. Please have a look. Thanks, martin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-21 1:36 ` mouse-drag-and-drop-region Tak Kunihiro 2017-12-22 8:43 ` mouse-drag-and-drop-region martin rudalics @ 2017-12-22 9:25 ` Eli Zaretskii 2017-12-22 17:57 ` mouse-drag-and-drop-region martin rudalics 1 sibling, 1 reply; 89+ messages in thread From: Eli Zaretskii @ 2017-12-22 9:25 UTC (permalink / raw) To: Tak Kunihiro; +Cc: rudalics, rswgnu, agrambot, emacs-devel > Date: Thu, 21 Dec 2017 10:36:46 +0900 (JST) > Cc: eliz@gnu.org, rswgnu@gmail.com, agrambot@gmail.com, > emacs-devel@gnu.org, tkk@misasa.okayama-u.ac.jp > From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp> > > diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi > index c94d690cf7..110199304e 100644 > --- a/doc/emacs/frames.texi > +++ b/doc/emacs/frames.texi > @@ -1106,6 +1106,14 @@ then pressing that modifier key when dropping the text will copy it > instead of cutting it, even if you drop on the same buffer as the one > from which the text came. > > +If you want to cut text even when source and destination buffers > +differ, set variable > +@code{mouse-drag-and-drop-region-cut-when-buffers-differ} to non-nil. > +If you do not want to see selected text in a tooltip in a graphic > +display and/or move point together with the mouse cursor during > +dragging, set @code{mouse-drag-and-drop-region-show-tooltip} and/or > +@code{mouse-drag-and-drop-region-show-cursor} to nil. > + > @vindex dnd-open-file-other-window > Dropping a file normally visits it in the window you drop it on. If > you prefer to visit the file in a new window in such cases, customize Thanks. When you describe in the manual functions or variables that were never described before, please always add index entries for them, using @findex or @vindex as appropriate. (I did it this time.) We want all the functions/variables mentioned in the manual to be indexed, so that their description could be easily found by users. Also, some documentation-related Emacs features rely on them being indexed, and will fail if they aren't. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: mouse-drag-and-drop-region 2017-12-22 9:25 ` mouse-drag-and-drop-region Eli Zaretskii @ 2017-12-22 17:57 ` martin rudalics 0 siblings, 0 replies; 89+ messages in thread From: martin rudalics @ 2017-12-22 17:57 UTC (permalink / raw) To: Eli Zaretskii, Tak Kunihiro; +Cc: rswgnu, agrambot, emacs-devel > When you describe in the manual functions or variables that were never > described before, please always add index entries for them, using > @findex or @vindex as appropriate. (I did it this time.) We want all > the functions/variables mentioned in the manual to be indexed, so that > their description could be easily found by users. Also, some > documentation-related Emacs features rely on them being indexed, and > will fail if they aren't. Thanks for the reminder. I tend to forget indexing when editing the Emacs manual. martin ^ permalink raw reply [flat|nested] 89+ messages in thread
end of thread, other threads:[~2017-12-22 17:57 UTC | newest] Thread overview: 89+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-11-14 9:54 mouse-drag-and-drop-region martin rudalics 2017-11-14 17:01 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-14 18:29 ` mouse-drag-and-drop-region martin rudalics 2017-11-14 20:17 ` mouse-drag-and-drop-region Alex 2017-11-15 9:22 ` mouse-drag-and-drop-region martin rudalics 2017-11-15 18:22 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-15 18:50 ` mouse-drag-and-drop-region martin rudalics 2017-11-15 20:01 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-16 9:04 ` mouse-drag-and-drop-region martin rudalics 2017-11-15 19:46 ` mouse-drag-and-drop-region Alex 2017-11-15 20:15 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-15 22:03 ` mouse-drag-and-drop-region Alex 2017-11-16 15:54 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-17 6:33 ` mouse-drag-and-drop-region Alex 2017-11-17 7:33 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-17 15:58 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-17 16:39 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-17 22:44 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-18 7:54 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-18 14:36 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-18 15:04 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-18 15:49 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-18 6:48 ` mouse-drag-and-drop-region Alex 2017-11-18 9:07 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-18 21:58 ` mouse-drag-and-drop-region Alex 2017-11-19 15:27 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-17 8:53 ` mouse-drag-and-drop-region martin rudalics 2017-11-18 6:49 ` mouse-drag-and-drop-region Alex 2017-11-16 9:04 ` mouse-drag-and-drop-region martin rudalics 2017-11-17 6:02 ` mouse-drag-and-drop-region Alex 2017-11-17 8:53 ` mouse-drag-and-drop-region martin rudalics 2017-11-15 20:22 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-16 0:28 ` mouse-drag-and-drop-region Tak Kunihiro 2017-11-16 9:11 ` mouse-drag-and-drop-region martin rudalics 2017-11-20 13:29 ` mouse-drag-and-drop-region Tak Kunihiro 2017-11-20 16:03 ` mouse-drag-and-drop-region Drew Adams 2017-11-20 16:09 ` mouse-drag-and-drop-region Alan Schmitt 2017-11-20 17:34 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-20 18:17 ` mouse-drag-and-drop-region Paul Eggert 2017-11-21 9:24 ` mouse-drag-and-drop-region martin rudalics 2017-11-21 13:09 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-21 14:05 ` mouse-drag-and-drop-region martin rudalics 2017-11-21 19:07 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-22 8:26 ` mouse-drag-and-drop-region martin rudalics 2017-11-22 21:20 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-23 7:46 ` mouse-drag-and-drop-region martin rudalics 2017-11-23 14:00 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-23 16:09 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-24 9:02 ` mouse-drag-and-drop-region martin rudalics 2017-11-24 9:19 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-24 9:41 ` mouse-drag-and-drop-region martin rudalics 2017-11-24 13:25 ` mouse-drag-and-drop-region Stefan Monnier 2017-11-26 10:24 ` mouse-drag-and-drop-region martin rudalics 2017-11-24 13:45 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-26 10:24 ` mouse-drag-and-drop-region martin rudalics 2017-11-26 15:54 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-27 8:48 ` mouse-drag-and-drop-region martin rudalics 2017-11-27 15:59 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-21 15:45 ` mouse-drag-and-drop-region Eli Zaretskii 2017-11-22 8:22 ` mouse-drag-and-drop-region martin rudalics 2017-11-21 18:52 ` mouse-drag-and-drop-region Robert Weiner 2017-11-22 8:22 ` mouse-drag-and-drop-region martin rudalics 2017-11-23 23:28 ` mouse-drag-and-drop-region Tak Kunihiro 2017-11-24 9:02 ` mouse-drag-and-drop-region martin rudalics 2017-11-27 13:11 ` mouse-drag-and-drop-region Tak Kunihiro 2017-11-28 8:50 ` mouse-drag-and-drop-region martin rudalics 2017-12-01 14:16 ` mouse-drag-and-drop-region Tak Kunihiro 2017-12-02 10:16 ` mouse-drag-and-drop-region martin rudalics 2017-12-03 10:06 ` mouse-drag-and-drop-region martin rudalics 2017-12-03 13:36 ` mouse-drag-and-drop-region martin rudalics 2017-12-05 4:57 ` mouse-drag-and-drop-region Tak Kunihiro 2017-12-05 8:53 ` mouse-drag-and-drop-region martin rudalics 2017-12-06 9:29 ` mouse-drag-and-drop-region Tak Kunihiro 2017-12-07 9:26 ` mouse-drag-and-drop-region martin rudalics 2017-12-07 21:45 ` mouse-drag-and-drop-region Tak Kunihiro 2017-12-08 10:12 ` mouse-drag-and-drop-region martin rudalics 2017-12-08 16:14 ` mouse-drag-and-drop-region Robert Weiner 2017-12-09 10:35 ` mouse-drag-and-drop-region martin rudalics 2017-12-14 23:14 ` mouse-drag-and-drop-region Tak Kunihiro 2017-12-15 8:50 ` mouse-drag-and-drop-region martin rudalics 2017-12-15 13:25 ` mouse-drag-and-drop-region martin rudalics 2017-12-16 2:07 ` mouse-drag-and-drop-region Tak Kunihiro 2017-12-16 9:42 ` mouse-drag-and-drop-region martin rudalics 2017-12-17 4:40 ` mouse-drag-and-drop-region Tak Kunihiro 2017-12-17 10:44 ` mouse-drag-and-drop-region martin rudalics 2017-12-21 1:36 ` mouse-drag-and-drop-region Tak Kunihiro 2017-12-22 8:43 ` mouse-drag-and-drop-region martin rudalics 2017-12-22 9:25 ` mouse-drag-and-drop-region Eli Zaretskii 2017-12-22 17:57 ` mouse-drag-and-drop-region martin rudalics
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.