Add support for 'dnd-scroll-margin' and 'dnd-indicate-insertion-point'
by calling 'dnd-handle-movement' when dragging the mouse.
* lisp/term/w32-win.el (w32-drag-n-drop): Call 'dnd-handle-movement'
when applicable.
* src/w32fns.c (w32_handle_drag_movement): New function, sends a
WM_EMACS_DRAGOVER message.
(w32_drop_target_DragEnter): Call 'w32_handle_drag_movement'.
(w32_drop_target_DragOver): Call 'w32_handle_drag_movement'.
* src/w32term.c: (w32_read_socket): Handle WM_EMACS_DRAGOVER,
sending a drag-n-drop event.
* src/w32term.h: Define new WM_EMACS_DRAGOVER message.
(cherry picked from commit
3eb2a85d10e0ad7b50e96ee4e80ba08b3a71b9ae)
---
** Emacs on MS-Windows now supports drag-n-drop of text into a buffer.
-This is in addition to drag-n-drop of files, that was already supported.
+This is in addition to drag-n-drop of files, that was already
+supported. The configuration variables 'dnd-scroll-margin' and
+'dnd-indicate-insertion-point' can be used to customize the process.
\f
If EVENT is for text, insert that text at point into the buffer
shown in the window that is the target of the drop; if that buffer is
read-only, add the dropped text to kill-ring.
+If EVENT payload is nil, then this is a drag event.
If the optional argument NEW-FRAME is non-nil, perform the
drag-n-drop action in a newly-created frame using its selected-window
and that window's buffer."
(interactive "e")
- (save-excursion
- ;; Make sure the drop target has positive co-ords
- ;; before setting the selected frame - otherwise it
- ;; won't work. <skx@tardis.ed.ac.uk>
- (let* ((window (posn-window (event-start event)))
- (coords (posn-x-y (event-start event)))
- (arg (car (cdr (cdr event))))
- (x (car coords))
- (y (cdr coords)))
- (if (and (> x 0) (> y 0))
- (set-frame-selected-window nil window))
-
- (when new-frame
- (select-frame (make-frame)))
- (raise-frame)
- (setq window (selected-window))
-
- ;; arg (the payload of the event) is a string when the drop is
- ;; text, and a list of strings when the drop is one or more files.
- (if (stringp arg)
- (dnd-insert-text window 'copy arg)
- (dnd-handle-multiple-urls
- window
- (mapcar #'w32-dropped-file-to-url arg)
- 'private)))))
+ ;; Make sure the drop target has positive co-ords
+ ;; before setting the selected frame - otherwise it
+ ;; won't work. <skx@tardis.ed.ac.uk>
+ (let* ((window (posn-window (event-start event)))
+ (coords (posn-x-y (event-start event)))
+ (arg (car (cdr (cdr event))))
+ (x (car coords))
+ (y (cdr coords)))
+
+ (if (and (> x 0) (> y 0) (window-live-p window))
+ (set-frame-selected-window nil window))
+ ;; Don't create new frame if we are just dragging
+ (and arg new-frame
+ (select-frame (make-frame)))
+ (raise-frame)
+ (setq window (selected-window))
+
+ ;; arg (the payload of the event) is a string when the drop is
+ ;; text, and a list of strings when the drop is one or more files.
+ ;; It is nil if the event is a drag event.
+ (if arg
+ (save-excursion
+ (if (stringp arg)
+ (dnd-insert-text window 'copy arg)
+ (dnd-handle-multiple-urls
+ window
+ (mapcar #'w32-dropped-file-to-url arg)
+ 'private)))
+ (dnd-handle-movement (event-start event)))))
(defun w32-drag-n-drop-other-frame (event)
"Edit the files listed in the drag-n-drop EVENT, in other frames.
return lisp_files;
}
-
/* This function can be called ONLY between calls to
block_input/unblock_input. It is used in w32_read_socket. */
Lisp_Object
return 0;
}
+static void
+w32_handle_drag_movement (IDropTarget *This, POINTL pt)
+{
+ struct w32_drop_target *target = (struct w32_drop_target *)This;
+
+ W32Msg msg = {0};
+ msg.dwModifiers = w32_get_modifiers ();
+ msg.msg.time = GetMessageTime ();
+ msg.msg.pt.x = pt.x;
+ msg.msg.pt.y = pt.y;
+ my_post_msg (&msg, target->hwnd, WM_EMACS_DRAGOVER, 0, 0 );
+}
+
static HRESULT STDMETHODCALLTYPE
w32_drop_target_DragEnter (IDropTarget *This, IDataObject *pDataObj,
DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
happen on drop. We send COPY because our use cases don't modify
or link to the original data. */
*pdwEffect = DROPEFFECT_COPY;
+ w32_handle_drag_movement (This, pt);
return S_OK;
}
{
/* See comment in w32_drop_target_DragEnter. */
*pdwEffect = DROPEFFECT_COPY;
+ w32_handle_drag_movement (This, pt);
return S_OK;
}
M (WM_EMACS_PAINT),
M (WM_EMACS_IME_STATUS),
M (WM_CHAR),
+ M (WM_EMACS_DRAGOVER),
M (WM_EMACS_DROP),
#undef M
{ 0, 0 }
}
break;
+ case WM_EMACS_DRAGOVER:
+ {
+ f = w32_window_to_frame (dpyinfo, msg.msg.hwnd);
+ if (!f)
+ break;
+ XSETFRAME (inev.frame_or_window, f);
+ inev.kind = DRAG_N_DROP_EVENT;
+ inev.code = 0;
+ inev.timestamp = msg.msg.time;
+ inev.modifiers = msg.dwModifiers;
+ ScreenToClient (msg.msg.hwnd, &msg.msg.pt);
+ XSETINT (inev.x, msg.msg.pt.x);
+ XSETINT (inev.y, msg.msg.pt.y);
+ /* This is a drag movement. */
+ inev.arg = Qnil;
+ break;
+ }
+
case WM_HSCROLL:
{
struct scroll_bar *bar =
#define WM_EMACS_INPUT_READY (WM_EMACS_START + 24)
#define WM_EMACS_FILENOTIFY (WM_EMACS_START + 25)
#define WM_EMACS_IME_STATUS (WM_EMACS_START + 26)
-#define WM_EMACS_DROP (WM_EMACS_START + 27)
-#define WM_EMACS_END (WM_EMACS_START + 28)
+#define WM_EMACS_DRAGOVER (WM_EMACS_START + 27)
+#define WM_EMACS_DROP (WM_EMACS_START + 28)
+#define WM_EMACS_END (WM_EMACS_START + 29)
#define WND_FONTWIDTH_INDEX (0)
#define WND_LINEHEIGHT_INDEX (4)