Fix two mouse drag and drop issues (Bug#28620, Bug#36269)
Allow 'mouse-drag-and-drop-region' to move/copy text from one frame to another (Bug#28620). Prevent mouse avoidance mode from interfering with 'mouse-drag-and-drop-region' (Bug#36269). * lisp/avoid.el (mouse-avoidance-ignore-p): Suspend avoidance when 'track-mouse' equals 'dropping'. * lisp/mouse.el (mouse-drag-and-drop-region): Set 'track-mouse' to 'dropping'. Continue reading events also when switching frames. * src/keyboard.c (Finternal_track_mouse): Rename from Ftrack_mouse. (some_mouse_moved): Return NULL also when mouse is not tracked. (show_help_echo, readable_events, kbd_buffer_get_event): Don't check whether mouse is tracked, some_mouse_moved does it now. (track_mouse): Rename variable from do_mouse_tracking. Adjust all users. In doc-string explain meanings of special values 'dragging' and 'dropping'. * src/nsterm.m (ns_mouse_position): During drag and drop consider last mouse frame only when there is no currently focused frame. * src/w32fns.c (w32_wnd_proc): Don't set mouse capture during a drag and drop operation. * src/w32term.c (w32_mouse_position): Track frame under mouse during mouse drag and drop. (mouse_or_wdesc_frame): New function. (w32_read_socket): Call mouse_or_wdesc_frame on mouse events. * src/xdisp.c (define_frame_cursor1): Don't change mouse cursor shape during mouse drag and drop. (syms_of_xdisp): New symbol Qdropping. * src/xterm.c (XTmouse_position): Allow mouse drag and drop move to another frame (mouse_or_wdesc_frame): New function. (handle_one_xevent): Use mouse_or_wdesc_frame for mouse events.
This commit is contained in:
parent
01661f33c1
commit
5ec3f70527
10 changed files with 242 additions and 159 deletions
|
@ -327,6 +327,9 @@ redefine this function to suit your own tastes."
|
|||
executing-kbd-macro ; don't check inside macro
|
||||
(null (cadr mp)) ; don't move unless in an Emacs frame
|
||||
(not (eq (car mp) (selected-frame)))
|
||||
;; Don't interfere with ongoing `mouse-drag-and-drop-region'
|
||||
;; (Bug#36269).
|
||||
(eq track-mouse 'dropping)
|
||||
;; Don't do anything if last event was a mouse event.
|
||||
;; FIXME: this code fails in the case where the mouse was moved
|
||||
;; since the last key-press but without generating any event.
|
||||
|
|
|
@ -1296,7 +1296,7 @@ The region will be defined with mark and point."
|
|||
t (lambda ()
|
||||
(setq track-mouse old-track-mouse)
|
||||
(setq auto-hscroll-mode auto-hscroll-mode-saved)
|
||||
(deactivate-mark)
|
||||
(deactivate-mark)
|
||||
(pop-mark)))))
|
||||
|
||||
(defun mouse--drag-set-mark-and-point (start click click-count)
|
||||
|
@ -2467,12 +2467,13 @@ is copied instead of being cut."
|
|||
|
||||
(ignore-errors
|
||||
(track-mouse
|
||||
(setq track-mouse 'dropping)
|
||||
;; 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)))
|
||||
(memq (car event) '(select-window switch-frame))))
|
||||
;; Obtain the dragged text in region. When the loop was
|
||||
;; skipped, value-selection remains nil.
|
||||
(unless value-selection
|
||||
|
|
|
@ -3402,9 +3402,9 @@ update_window (struct window *w, bool force_p)
|
|||
if (!force_p)
|
||||
detect_input_pending_ignore_squeezables ();
|
||||
|
||||
/* If forced to complete the update, or if no input is pending, do
|
||||
the update. */
|
||||
if (force_p || !input_pending || !NILP (do_mouse_tracking))
|
||||
/* If forced to complete the update, no input is pending, or we are
|
||||
tracking the mouse, do the update. */
|
||||
if (force_p || !input_pending || !NILP (track_mouse))
|
||||
{
|
||||
struct glyph_row *row, *end;
|
||||
struct glyph_row *mode_line_row;
|
||||
|
|
|
@ -1159,14 +1159,14 @@ DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0,
|
|||
user_error ("No recursive edit is in progress");
|
||||
}
|
||||
|
||||
/* Restore mouse tracking enablement. See Ftrack_mouse for the only use
|
||||
of this function. */
|
||||
/* Restore mouse tracking enablement. See Finternal_track_mouse for
|
||||
the only use of this function. */
|
||||
|
||||
static void
|
||||
tracking_off (Lisp_Object old_value)
|
||||
tracking_off (Lisp_Object old_track_mouse)
|
||||
{
|
||||
do_mouse_tracking = old_value;
|
||||
if (NILP (old_value))
|
||||
track_mouse = old_track_mouse;
|
||||
if (NILP (old_track_mouse))
|
||||
{
|
||||
/* Redisplay may have been preempted because there was input
|
||||
available, and it assumes it will be called again after the
|
||||
|
@ -1181,24 +1181,24 @@ tracking_off (Lisp_Object old_value)
|
|||
}
|
||||
}
|
||||
|
||||
DEFUN ("internal--track-mouse", Ftrack_mouse, Strack_mouse, 1, 1, 0,
|
||||
DEFUN ("internal--track-mouse", Finternal_track_mouse, Sinternal_track_mouse,
|
||||
1, 1, 0,
|
||||
doc: /* Call BODYFUN with mouse movement events enabled. */)
|
||||
(Lisp_Object bodyfun)
|
||||
{
|
||||
ptrdiff_t count = SPECPDL_INDEX ();
|
||||
Lisp_Object val;
|
||||
|
||||
record_unwind_protect (tracking_off, do_mouse_tracking);
|
||||
record_unwind_protect (tracking_off, track_mouse);
|
||||
|
||||
do_mouse_tracking = Qt;
|
||||
track_mouse = Qt;
|
||||
|
||||
val = call0 (bodyfun);
|
||||
return unbind_to (count, val);
|
||||
}
|
||||
|
||||
/* If mouse has moved on some frame, return one of those frames.
|
||||
|
||||
Return 0 otherwise.
|
||||
/* If mouse has moved on some frame and we are tracking the mouse,
|
||||
return one of those frames. Return NULL otherwise.
|
||||
|
||||
If ignore_mouse_drag_p is non-zero, ignore (implicit) mouse movement
|
||||
after resizing the tool-bar window. */
|
||||
|
@ -1210,11 +1210,8 @@ some_mouse_moved (void)
|
|||
{
|
||||
Lisp_Object tail, frame;
|
||||
|
||||
if (ignore_mouse_drag_p)
|
||||
{
|
||||
/* ignore_mouse_drag_p = false; */
|
||||
return 0;
|
||||
}
|
||||
if (NILP (track_mouse) || ignore_mouse_drag_p)
|
||||
return NULL;
|
||||
|
||||
FOR_EACH_FRAME (tail, frame)
|
||||
{
|
||||
|
@ -1222,7 +1219,7 @@ some_mouse_moved (void)
|
|||
return XFRAME (frame);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2071,7 +2068,8 @@ show_help_echo (Lisp_Object help, Lisp_Object window, Lisp_Object object,
|
|||
This causes trouble if we are trying to read a mouse motion
|
||||
event (i.e., if we are inside a `track-mouse' form), so we
|
||||
restore the mouse_moved flag. */
|
||||
struct frame *f = NILP (do_mouse_tracking) ? NULL : some_mouse_moved ();
|
||||
struct frame *f = some_mouse_moved ();
|
||||
|
||||
help = call1 (Qmouse_fixup_help_message, help);
|
||||
if (f)
|
||||
f->mouse_moved = true;
|
||||
|
@ -3403,8 +3401,7 @@ readable_events (int flags)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!(flags & READABLE_EVENTS_IGNORE_SQUEEZABLES)
|
||||
&& !NILP (do_mouse_tracking) && some_mouse_moved ())
|
||||
if (!(flags & READABLE_EVENTS_IGNORE_SQUEEZABLES) && some_mouse_moved ())
|
||||
return 1;
|
||||
if (single_kboard)
|
||||
{
|
||||
|
@ -3786,7 +3783,7 @@ kbd_buffer_get_event (KBOARD **kbp,
|
|||
|
||||
if (kbd_fetch_ptr != kbd_store_ptr)
|
||||
break;
|
||||
if (!NILP (do_mouse_tracking) && some_mouse_moved ())
|
||||
if (some_mouse_moved ())
|
||||
break;
|
||||
|
||||
/* If the quit flag is set, then read_char will return
|
||||
|
@ -3802,7 +3799,7 @@ kbd_buffer_get_event (KBOARD **kbp,
|
|||
#endif
|
||||
if (kbd_fetch_ptr != kbd_store_ptr)
|
||||
break;
|
||||
if (!NILP (do_mouse_tracking) && some_mouse_moved ())
|
||||
if (some_mouse_moved ())
|
||||
break;
|
||||
if (end_time)
|
||||
{
|
||||
|
@ -3941,8 +3938,9 @@ kbd_buffer_get_event (KBOARD **kbp,
|
|||
break;
|
||||
default:
|
||||
{
|
||||
/* If this event is on a different frame, return a switch-frame this
|
||||
time, and leave the event in the queue for next time. */
|
||||
/* If this event is on a different frame, return a
|
||||
switch-frame this time, and leave the event in the queue
|
||||
for next time. */
|
||||
Lisp_Object frame;
|
||||
Lisp_Object focus;
|
||||
|
||||
|
@ -3956,14 +3954,13 @@ kbd_buffer_get_event (KBOARD **kbp,
|
|||
if (! NILP (focus))
|
||||
frame = focus;
|
||||
|
||||
if (! EQ (frame, internal_last_event_frame)
|
||||
if (!EQ (frame, internal_last_event_frame)
|
||||
&& !EQ (frame, selected_frame))
|
||||
obj = make_lispy_switch_frame (frame);
|
||||
internal_last_event_frame = frame;
|
||||
|
||||
/* If we didn't decide to make a switch-frame event, go ahead
|
||||
and build a real event from the queue entry. */
|
||||
|
||||
if (NILP (obj))
|
||||
{
|
||||
obj = make_lispy_event (&event->ie);
|
||||
|
@ -3995,7 +3992,7 @@ kbd_buffer_get_event (KBOARD **kbp,
|
|||
}
|
||||
}
|
||||
/* Try generating a mouse motion event. */
|
||||
else if (!NILP (do_mouse_tracking) && some_mouse_moved ())
|
||||
else if (some_mouse_moved ())
|
||||
{
|
||||
struct frame *f = some_mouse_moved ();
|
||||
Lisp_Object bar_window;
|
||||
|
@ -4027,7 +4024,7 @@ kbd_buffer_get_event (KBOARD **kbp,
|
|||
if (NILP (frame))
|
||||
XSETFRAME (frame, f);
|
||||
|
||||
if (! EQ (frame, internal_last_event_frame)
|
||||
if (!EQ (frame, internal_last_event_frame)
|
||||
&& !EQ (frame, selected_frame))
|
||||
obj = make_lispy_switch_frame (frame);
|
||||
internal_last_event_frame = frame;
|
||||
|
@ -10935,7 +10932,7 @@ init_keyboard (void)
|
|||
recent_keys_index = 0;
|
||||
kbd_fetch_ptr = kbd_buffer;
|
||||
kbd_store_ptr = kbd_buffer;
|
||||
do_mouse_tracking = Qnil;
|
||||
track_mouse = Qnil;
|
||||
input_pending = false;
|
||||
interrupt_input_blocked = 0;
|
||||
pending_signals = false;
|
||||
|
@ -11297,7 +11294,7 @@ syms_of_keyboard (void)
|
|||
defsubr (&Sread_key_sequence);
|
||||
defsubr (&Sread_key_sequence_vector);
|
||||
defsubr (&Srecursive_edit);
|
||||
defsubr (&Strack_mouse);
|
||||
defsubr (&Sinternal_track_mouse);
|
||||
defsubr (&Sinput_pending_p);
|
||||
defsubr (&Srecent_keys);
|
||||
defsubr (&Sthis_command_keys);
|
||||
|
@ -11643,8 +11640,15 @@ and the minor mode maps regardless of `overriding-local-map'. */);
|
|||
doc: /* Keymap defining bindings for special events to execute at low level. */);
|
||||
Vspecial_event_map = list1 (Qkeymap);
|
||||
|
||||
DEFVAR_LISP ("track-mouse", do_mouse_tracking,
|
||||
doc: /* Non-nil means generate motion events for mouse motion. */);
|
||||
DEFVAR_LISP ("track-mouse", track_mouse,
|
||||
doc: /* Non-nil means generate motion events for mouse motion.
|
||||
The special values `dragging' and `dropping' assert that the mouse
|
||||
cursor retains its appearance during mouse motion. Any non-nil value
|
||||
but `dropping' asserts that motion events always relate to the frame
|
||||
where the the mouse movement started. The value `dropping' asserts
|
||||
that motion events relate to the frame where the mouse cursor is seen
|
||||
when generating the event. If there's no such frame, such motion
|
||||
events relate to the frame where the mouse movement started. */);
|
||||
|
||||
DEFVAR_KBOARD ("system-key-alist", Vsystem_key_alist,
|
||||
doc: /* Alist of system-specific X windows key symbols.
|
||||
|
|
|
@ -2480,7 +2480,11 @@ so some key presses (TAB) are swallowed by the system. */
|
|||
XFRAME (frame)->mouse_moved = 0;
|
||||
|
||||
dpyinfo->last_mouse_scroll_bar = nil;
|
||||
f = dpyinfo->ns_focus_frame ? dpyinfo->ns_focus_frame : SELECTED_FRAME ();
|
||||
if (dpyinfo->last_mouse_frame
|
||||
/* While dropping, use the last mouse frame only if there is no
|
||||
currently focused frame. */
|
||||
&& (!EQ (track_mouse, Qdropping) || !f)
|
||||
&& FRAME_LIVE_P (dpyinfo->last_mouse_frame))
|
||||
f = dpyinfo->last_mouse_frame;
|
||||
else
|
||||
|
|
|
@ -3033,18 +3033,18 @@ read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
|
|||
bool usable_input = 1;
|
||||
mi_result st = MI_CONTINUE;
|
||||
struct tty_display_info *tty = FRAME_TTY (sf);
|
||||
Lisp_Object saved_mouse_tracking = do_mouse_tracking;
|
||||
Lisp_Object old_track_mouse = track_mouse;
|
||||
|
||||
/* Signal the keyboard reading routines we are displaying a menu
|
||||
on this terminal. */
|
||||
tty->showing_menu = 1;
|
||||
/* We want mouse movements be reported by read_menu_command. */
|
||||
do_mouse_tracking = Qt;
|
||||
track_mouse = Qt;
|
||||
do {
|
||||
cmd = read_menu_command ();
|
||||
} while (NILP (cmd));
|
||||
tty->showing_menu = 0;
|
||||
do_mouse_tracking = saved_mouse_tracking;
|
||||
track_mouse = old_track_mouse;
|
||||
|
||||
if (EQ (cmd, Qt) || EQ (cmd, Qtty_menu_exit)
|
||||
/* If some input switched frames under our feet, exit the
|
||||
|
|
15
src/w32fns.c
15
src/w32fns.c
|
@ -4586,7 +4586,8 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
if (button_state & this)
|
||||
return 0;
|
||||
|
||||
if (button_state == 0)
|
||||
/* Don't capture mouse when dropping. */
|
||||
if (button_state == 0 && !EQ (track_mouse, Qdropping))
|
||||
SetCapture (hwnd);
|
||||
|
||||
button_state |= this;
|
||||
|
@ -4707,8 +4708,11 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
if (parse_button (msg, HIWORD (wParam), &button, &up))
|
||||
{
|
||||
if (up) ReleaseCapture ();
|
||||
else SetCapture (hwnd);
|
||||
if (up)
|
||||
ReleaseCapture ();
|
||||
/* Don't capture mouse when dropping. */
|
||||
else if (!EQ (track_mouse, Qdropping))
|
||||
SetCapture (hwnd);
|
||||
button = (button == 0) ? LMOUSE :
|
||||
((button == 1) ? MMOUSE : RMOUSE);
|
||||
if (up)
|
||||
|
@ -5351,8 +5355,9 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
else if (button_state & RMOUSE)
|
||||
flags |= TPM_RIGHTBUTTON;
|
||||
|
||||
/* Remember we did a SetCapture on the initial mouse down event,
|
||||
so for safety, we make sure the capture is canceled now. */
|
||||
/* We may have done a SetCapture on the initial mouse down
|
||||
event, so for safety, make sure the capture is canceled
|
||||
now. */
|
||||
ReleaseCapture ();
|
||||
button_state = 0;
|
||||
|
||||
|
|
164
src/w32term.c
164
src/w32term.c
|
@ -3525,72 +3525,78 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
|
|||
|
||||
/* Now we have a position on the root; find the innermost window
|
||||
containing the pointer. */
|
||||
{
|
||||
/* If mouse was grabbed on a frame, give coords for that
|
||||
frame even if the mouse is now outside it. Otherwise
|
||||
check for window under mouse on one of our frames. */
|
||||
if (gui_mouse_grabbed (dpyinfo))
|
||||
f1 = dpyinfo->last_mouse_frame;
|
||||
else
|
||||
{
|
||||
HWND wfp = WindowFromPoint (pt);
|
||||
|
||||
if (wfp)
|
||||
{
|
||||
f1 = w32_window_to_frame (dpyinfo, wfp);
|
||||
if (f1)
|
||||
{
|
||||
HWND cwfp = ChildWindowFromPoint (wfp, pt);
|
||||
/* If mouse was grabbed on a frame and we are not dropping,
|
||||
give coords for that frame even if the mouse is now outside
|
||||
it. Otherwise check for window under mouse on one of our
|
||||
frames. */
|
||||
if (gui_mouse_grabbed (dpyinfo) && !EQ (track_mouse, Qdropping))
|
||||
f1 = dpyinfo->last_mouse_frame;
|
||||
else
|
||||
{
|
||||
HWND wfp = WindowFromPoint (pt);
|
||||
|
||||
if (cwfp)
|
||||
{
|
||||
struct frame *f2 = w32_window_to_frame (dpyinfo, cwfp);
|
||||
if (wfp)
|
||||
{
|
||||
f1 = w32_window_to_frame (dpyinfo, wfp);
|
||||
if (f1)
|
||||
{
|
||||
HWND cwfp = ChildWindowFromPoint (wfp, pt);
|
||||
|
||||
/* If a child window was found, make sure that its
|
||||
frame is a child frame (Bug#26615, maybe). */
|
||||
if (f2 && FRAME_PARENT_FRAME (f2))
|
||||
f1 = f2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cwfp)
|
||||
{
|
||||
struct frame *f2 = w32_window_to_frame (dpyinfo, cwfp);
|
||||
|
||||
/* If not, is it one of our scroll bars? */
|
||||
if (! f1)
|
||||
{
|
||||
struct scroll_bar *bar
|
||||
= w32_window_to_scroll_bar (WindowFromPoint (pt), 2);
|
||||
/* If a child window was found, make sure that its
|
||||
frame is a child frame (Bug#26615, maybe). */
|
||||
if (f2 && FRAME_PARENT_FRAME (f2))
|
||||
f1 = f2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bar)
|
||||
f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
|
||||
}
|
||||
if (!f1 || FRAME_TOOLTIP_P (f1))
|
||||
/* Don't use a tooltip frame. */
|
||||
f1 = ((EQ (track_mouse, Qdropping) && gui_mouse_grabbed (dpyinfo))
|
||||
? dpyinfo->last_mouse_frame
|
||||
: NULL);
|
||||
|
||||
if (f1 == 0 && insist > 0)
|
||||
f1 = SELECTED_FRAME ();
|
||||
/* If not, is it one of our scroll bars? */
|
||||
if (!f1)
|
||||
{
|
||||
struct scroll_bar *bar
|
||||
= w32_window_to_scroll_bar (WindowFromPoint (pt), 2);
|
||||
|
||||
if (f1)
|
||||
{
|
||||
/* Ok, we found a frame. Store all the values.
|
||||
last_mouse_glyph is a rectangle used to reduce the
|
||||
generation of mouse events. To not miss any motion
|
||||
events, we must divide the frame into rectangles of the
|
||||
size of the smallest character that could be displayed
|
||||
on it, i.e. into the same rectangles that matrices on
|
||||
the frame are divided into. */
|
||||
if (bar)
|
||||
f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
|
||||
}
|
||||
|
||||
dpyinfo = FRAME_DISPLAY_INFO (f1);
|
||||
ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
|
||||
remember_mouse_glyph (f1, pt.x, pt.y, &dpyinfo->last_mouse_glyph);
|
||||
dpyinfo->last_mouse_glyph_frame = f1;
|
||||
if (!f1 && insist > 0)
|
||||
f1 = SELECTED_FRAME ();
|
||||
|
||||
*bar_window = Qnil;
|
||||
*part = scroll_bar_above_handle;
|
||||
*fp = f1;
|
||||
XSETINT (*x, pt.x);
|
||||
XSETINT (*y, pt.y);
|
||||
*time = dpyinfo->last_mouse_movement_time;
|
||||
}
|
||||
}
|
||||
if (f1)
|
||||
{
|
||||
/* Ok, we found a frame. Store all the values.
|
||||
last_mouse_glyph is a rectangle used to reduce the
|
||||
generation of mouse events. To not miss any motion
|
||||
events, we must divide the frame into rectangles of the
|
||||
size of the smallest character that could be displayed
|
||||
on it, i.e. into the same rectangles that matrices on
|
||||
the frame are divided into. */
|
||||
|
||||
dpyinfo = FRAME_DISPLAY_INFO (f1);
|
||||
ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
|
||||
remember_mouse_glyph (f1, pt.x, pt.y, &dpyinfo->last_mouse_glyph);
|
||||
dpyinfo->last_mouse_glyph_frame = f1;
|
||||
|
||||
*bar_window = Qnil;
|
||||
*part = scroll_bar_above_handle;
|
||||
*fp = f1;
|
||||
XSETINT (*x, pt.x);
|
||||
XSETINT (*y, pt.y);
|
||||
*time = dpyinfo->last_mouse_movement_time;
|
||||
}
|
||||
}
|
||||
|
||||
unblock_input ();
|
||||
|
@ -4667,6 +4673,37 @@ static short temp_buffer[100];
|
|||
/* Temporarily store lead byte of DBCS input sequences. */
|
||||
static char dbcs_lead = 0;
|
||||
|
||||
/**
|
||||
mouse_or_wdesc_frame: When not dropping and the mouse was grabbed
|
||||
for DPYINFO, return the frame where the mouse was seen last. If
|
||||
there's no such frame, return the frame according to WDESC. When
|
||||
dropping, return the frame according to WDESC. If there's no such
|
||||
frame and the mouse was grabbed for DPYINFO, return the frame where
|
||||
the mouse was seen last. In either case, never return a tooltip
|
||||
frame. */
|
||||
static struct frame *
|
||||
mouse_or_wdesc_frame (struct w32_display_info *dpyinfo, HWND wdesc)
|
||||
{
|
||||
struct frame *lm_f = (gui_mouse_grabbed (dpyinfo)
|
||||
? dpyinfo->last_mouse_frame
|
||||
: NULL);
|
||||
|
||||
if (lm_f && !EQ (track_mouse, Qdropping))
|
||||
return lm_f;
|
||||
else
|
||||
{
|
||||
struct frame *w_f = w32_window_to_frame (dpyinfo, wdesc);
|
||||
|
||||
/* Do not return a tooltip frame. */
|
||||
if (!w_f || FRAME_TOOLTIP_P (w_f))
|
||||
return EQ (track_mouse, Qdropping) ? lm_f : NULL;
|
||||
else
|
||||
/* When dropping it would be probably nice to raise w_f
|
||||
here. */
|
||||
return w_f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read events coming from the W32 shell.
|
||||
This routine is called by the SIGIO handler.
|
||||
We return as soon as there are no more events to be read.
|
||||
|
@ -4940,15 +4977,13 @@ w32_read_socket (struct terminal *terminal,
|
|||
previous_help_echo_string = help_echo_string;
|
||||
help_echo_string = Qnil;
|
||||
|
||||
f = (gui_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
|
||||
: w32_window_to_frame (dpyinfo, msg.msg.hwnd));
|
||||
|
||||
if (hlinfo->mouse_face_hidden)
|
||||
{
|
||||
hlinfo->mouse_face_hidden = false;
|
||||
clear_mouse_face (hlinfo);
|
||||
}
|
||||
|
||||
f = mouse_or_wdesc_frame (dpyinfo, msg.msg.hwnd);
|
||||
if (f)
|
||||
{
|
||||
/* Maybe generate SELECT_WINDOW_EVENTs for
|
||||
|
@ -5020,9 +5055,7 @@ w32_read_socket (struct terminal *terminal,
|
|||
int button = 0;
|
||||
int up = 0;
|
||||
|
||||
f = (gui_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
|
||||
: w32_window_to_frame (dpyinfo, msg.msg.hwnd));
|
||||
|
||||
f = mouse_or_wdesc_frame (dpyinfo, msg.msg.hwnd);
|
||||
if (f)
|
||||
{
|
||||
w32_construct_mouse_click (&inev, &msg, f);
|
||||
|
@ -5081,9 +5114,7 @@ w32_read_socket (struct terminal *terminal,
|
|||
case WM_MOUSEWHEEL:
|
||||
case WM_MOUSEHWHEEL:
|
||||
{
|
||||
f = (gui_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
|
||||
: w32_window_to_frame (dpyinfo, msg.msg.hwnd));
|
||||
|
||||
f = mouse_or_wdesc_frame (dpyinfo, msg.msg.hwnd);
|
||||
if (f)
|
||||
{
|
||||
if (!dpyinfo->w32_focus_frame
|
||||
|
@ -5439,6 +5470,7 @@ w32_read_socket (struct terminal *terminal,
|
|||
if (any_help_event_p)
|
||||
do_help = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WM_SETFOCUS:
|
||||
|
|
|
@ -17289,7 +17289,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
|
|||
the mouse, resulting in an unwanted mouse-movement rather
|
||||
than a simple mouse-click. */
|
||||
if (!w->start_at_line_beg
|
||||
&& NILP (do_mouse_tracking)
|
||||
&& NILP (track_mouse)
|
||||
&& CHARPOS (startp) > BEGV
|
||||
&& CHARPOS (startp) > BEG + beg_unchanged
|
||||
&& CHARPOS (startp) <= Z - end_unchanged
|
||||
|
@ -30279,7 +30279,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
|
|||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
/* Change the mouse cursor. */
|
||||
if (FRAME_WINDOW_P (f) && NILP (do_mouse_tracking))
|
||||
if (FRAME_WINDOW_P (f) && NILP (track_mouse))
|
||||
{
|
||||
#ifndef HAVE_EXT_TOOL_BAR
|
||||
if (draw == DRAW_NORMAL_TEXT
|
||||
|
@ -31226,7 +31226,7 @@ define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
|
|||
return;
|
||||
|
||||
/* Do not change cursor shape while dragging mouse. */
|
||||
if (EQ (do_mouse_tracking, Qdragging))
|
||||
if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping))
|
||||
return;
|
||||
|
||||
if (!NILP (pointer))
|
||||
|
@ -32956,6 +32956,7 @@ be let-bound around code that needs to disable messages temporarily. */);
|
|||
/* also Qtext */
|
||||
|
||||
DEFSYM (Qdragging, "dragging");
|
||||
DEFSYM (Qdropping, "dropping");
|
||||
|
||||
DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
|
||||
|
||||
|
|
123
src/xterm.c
123
src/xterm.c
|
@ -5196,20 +5196,15 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
|
|||
/* Figure out which root window we're on. */
|
||||
XQueryPointer (FRAME_X_DISPLAY (*fp),
|
||||
DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
|
||||
|
||||
/* The root window which contains the pointer. */
|
||||
&root,
|
||||
|
||||
/* Trash which we can't trust if the pointer is on
|
||||
a different screen. */
|
||||
&dummy_window,
|
||||
|
||||
/* The position on that root window. */
|
||||
&root_x, &root_y,
|
||||
|
||||
/* More trash we can't trust. */
|
||||
&dummy, &dummy,
|
||||
|
||||
/* Modifier keys and pointer buttons, about which
|
||||
we don't care. */
|
||||
(unsigned int *) &dummy);
|
||||
|
@ -5232,21 +5227,17 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
|
|||
|
||||
x_catch_errors (FRAME_X_DISPLAY (*fp));
|
||||
|
||||
if (gui_mouse_grabbed (dpyinfo))
|
||||
if (gui_mouse_grabbed (dpyinfo) && !EQ (track_mouse, Qdropping))
|
||||
{
|
||||
/* If mouse was grabbed on a frame, give coords for that frame
|
||||
even if the mouse is now outside it. */
|
||||
XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
|
||||
|
||||
/* From-window. */
|
||||
root,
|
||||
|
||||
/* To-window. */
|
||||
FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
|
||||
|
||||
/* From-position, to-position. */
|
||||
root_x, root_y, &win_x, &win_y,
|
||||
|
||||
/* Child of win. */
|
||||
&child);
|
||||
f1 = dpyinfo->last_mouse_frame;
|
||||
|
@ -5256,16 +5247,12 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
|
|||
while (true)
|
||||
{
|
||||
XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
|
||||
|
||||
/* From-window, to-window. */
|
||||
root, win,
|
||||
|
||||
/* From-position, to-position. */
|
||||
root_x, root_y, &win_x, &win_y,
|
||||
|
||||
/* Child of win. */
|
||||
&child);
|
||||
|
||||
if (child == None || child == win)
|
||||
{
|
||||
#ifdef USE_GTK
|
||||
|
@ -5328,13 +5315,35 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
|
|||
#endif /* USE_X_TOOLKIT */
|
||||
}
|
||||
|
||||
if ((!f1 || FRAME_TOOLTIP_P (f1))
|
||||
&& EQ (track_mouse, Qdropping)
|
||||
&& gui_mouse_grabbed (dpyinfo))
|
||||
{
|
||||
/* When dropping then if we didn't get a frame or only a
|
||||
tooltip frame and the mouse was grabbed on a frame,
|
||||
give coords for that frame even if the mouse is now
|
||||
outside it. */
|
||||
XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
|
||||
/* From-window. */
|
||||
root,
|
||||
/* To-window. */
|
||||
FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
|
||||
/* From-position, to-position. */
|
||||
root_x, root_y, &win_x, &win_y,
|
||||
/* Child of win. */
|
||||
&child);
|
||||
f1 = dpyinfo->last_mouse_frame;
|
||||
}
|
||||
else if (f1 && FRAME_TOOLTIP_P (f1))
|
||||
f1 = NULL;
|
||||
|
||||
if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
|
||||
f1 = 0;
|
||||
f1 = NULL;
|
||||
|
||||
x_uncatch_errors_after_check ();
|
||||
|
||||
/* If not, is it one of our scroll bars? */
|
||||
if (! f1)
|
||||
if (!f1)
|
||||
{
|
||||
struct scroll_bar *bar;
|
||||
|
||||
|
@ -5348,7 +5357,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
|
|||
}
|
||||
}
|
||||
|
||||
if (f1 == 0 && insist > 0)
|
||||
if (!f1 && insist > 0)
|
||||
f1 = SELECTED_FRAME ();
|
||||
|
||||
if (f1)
|
||||
|
@ -7817,6 +7826,37 @@ flush_dirty_back_buffers (void)
|
|||
unblock_input ();
|
||||
}
|
||||
|
||||
/**
|
||||
mouse_or_wdesc_frame: When not dropping and the mouse was grabbed
|
||||
for DPYINFO, return the frame where the mouse was seen last. If
|
||||
there's no such frame, return the frame according to WDESC. When
|
||||
dropping, return the frame according to WDESC. If there's no such
|
||||
frame and the mouse was grabbed for DPYINFO, return the frame where
|
||||
the mouse was seen last. In either case, never return a tooltip
|
||||
frame. */
|
||||
static struct frame *
|
||||
mouse_or_wdesc_frame (struct x_display_info *dpyinfo, int wdesc)
|
||||
{
|
||||
struct frame *lm_f = (gui_mouse_grabbed (dpyinfo)
|
||||
? dpyinfo->last_mouse_frame
|
||||
: NULL);
|
||||
|
||||
if (lm_f && !EQ (track_mouse, Qdropping))
|
||||
return lm_f;
|
||||
else
|
||||
{
|
||||
struct frame *w_f = x_window_to_frame (dpyinfo, wdesc);
|
||||
|
||||
/* Do not return a tooltip frame. */
|
||||
if (!w_f || FRAME_TOOLTIP_P (w_f))
|
||||
return EQ (track_mouse, Qdropping) ? lm_f : NULL;
|
||||
else
|
||||
/* When dropping it would be probably nice to raise w_f
|
||||
here. */
|
||||
return w_f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handles the XEvent EVENT on display DPYINFO.
|
||||
|
||||
*FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
|
||||
|
@ -8749,15 +8789,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
|||
previous_help_echo_string = help_echo_string;
|
||||
help_echo_string = Qnil;
|
||||
|
||||
f = (gui_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
|
||||
: x_window_to_frame (dpyinfo, event->xmotion.window));
|
||||
|
||||
if (hlinfo->mouse_face_hidden)
|
||||
if (hlinfo->mouse_face_hidden)
|
||||
{
|
||||
hlinfo->mouse_face_hidden = false;
|
||||
clear_mouse_face (hlinfo);
|
||||
}
|
||||
|
||||
f = mouse_or_wdesc_frame (dpyinfo, event->xmotion.window);
|
||||
|
||||
#ifdef USE_GTK
|
||||
if (f && xg_event_is_for_scrollbar (f, event))
|
||||
f = 0;
|
||||
|
@ -8999,33 +9038,27 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|
|||
dpyinfo->last_mouse_glyph_frame = NULL;
|
||||
x_display_set_last_user_time (dpyinfo, event->xbutton.time);
|
||||
|
||||
if (gui_mouse_grabbed (dpyinfo))
|
||||
f = dpyinfo->last_mouse_frame;
|
||||
else
|
||||
f = mouse_or_wdesc_frame (dpyinfo, event->xmotion.window);
|
||||
if (f && event->xbutton.type == ButtonPress
|
||||
&& !popup_activated ()
|
||||
&& !x_window_to_scroll_bar (event->xbutton.display,
|
||||
event->xbutton.window, 2)
|
||||
&& !FRAME_NO_ACCEPT_FOCUS (f))
|
||||
{
|
||||
f = x_window_to_frame (dpyinfo, event->xbutton.window);
|
||||
/* When clicking into a child frame or when clicking
|
||||
into a parent frame with the child frame selected and
|
||||
`no-accept-focus' is not set, select the clicked
|
||||
frame. */
|
||||
struct frame *hf = dpyinfo->highlight_frame;
|
||||
|
||||
if (f && event->xbutton.type == ButtonPress
|
||||
&& !popup_activated ()
|
||||
&& !x_window_to_scroll_bar (event->xbutton.display,
|
||||
event->xbutton.window, 2)
|
||||
&& !FRAME_NO_ACCEPT_FOCUS (f))
|
||||
if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
|
||||
{
|
||||
/* When clicking into a child frame or when clicking
|
||||
into a parent frame with the child frame selected and
|
||||
`no-accept-focus' is not set, select the clicked
|
||||
frame. */
|
||||
struct frame *hf = dpyinfo->highlight_frame;
|
||||
|
||||
if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
|
||||
{
|
||||
block_input ();
|
||||
XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
RevertToParent, CurrentTime);
|
||||
if (FRAME_PARENT_FRAME (f))
|
||||
XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
|
||||
unblock_input ();
|
||||
}
|
||||
block_input ();
|
||||
XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
RevertToParent, CurrentTime);
|
||||
if (FRAME_PARENT_FRAME (f))
|
||||
XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
|
||||
unblock_input ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue