From: Po Lu Date: Sun, 3 Apr 2022 11:33:52 +0000 (+0800) Subject: Implement `drag-source' values of `track-mouse' on PGTK. X-Git-Tag: emacs-29.0.90~1931^2~800 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=1fb20a4dde8c63a1aae570b59bb4bbb02673bec9;p=emacs.git Implement `drag-source' values of `track-mouse' on PGTK. * src/frame.c (Fmouse_position, mouse_position) (Fmouse_pixel_position): Fix crashes when mouse_position_hook stores nil. * src/pgtkterm.c (pgtk_mouse_position): Behave appropriately. --- diff --git a/src/frame.c b/src/frame.c index e531891a8a3..7a9ed3302e4 100644 --- a/src/frame.c +++ b/src/frame.c @@ -2505,9 +2505,12 @@ vertical offset, measured in units of the frame's default character size. If Emacs is running on a mouseless terminal or hasn't been programmed to read the mouse position, it returns the selected frame for FRAME and nil for X and Y. -If `mouse-position-function' is non-nil, `mouse-position' calls it, -passing the normal return value to that function as an argument, -and returns whatever that function returns. */) + +FRAME might be nil if `track-mouse' is set to `drag-source'. This +means there is no frame under the mouse. If `mouse-position-function' +is non-nil, `mouse-position' calls it, passing the normal return value +to that function as an argument, and returns whatever that function +returns. */) (void) { return mouse_position (true); @@ -2534,7 +2537,7 @@ mouse_position (bool call_mouse_position_function) &time_dummy); } - if (! NILP (x)) + if (! NILP (x) && f) { int col = XFIXNUM (x); int row = XFIXNUM (y); @@ -2542,7 +2545,10 @@ mouse_position (bool call_mouse_position_function) XSETINT (x, col); XSETINT (y, row); } - XSETFRAME (lispy_dummy, f); + if (f) + XSETFRAME (lispy_dummy, f); + else + lispy_dummy = Qnil; retval = Fcons (lispy_dummy, Fcons (x, y)); if (call_mouse_position_function && !NILP (Vmouse_position_function)) retval = call1 (Vmouse_position_function, retval); @@ -2555,9 +2561,11 @@ DEFUN ("mouse-pixel-position", Fmouse_pixel_position, The position is given in pixel units, where (0, 0) is the upper-left corner of the frame, X is the horizontal offset, and Y is the vertical offset. -If Emacs is running on a mouseless terminal or hasn't been programmed -to read the mouse position, it returns the selected frame for FRAME -and nil for X and Y. */) +FRAME might be nil if `track-mouse' is set to `drag-source'. This +means there is no frame under the mouse. If Emacs is running on a +mouseless terminal or hasn't been programmed to read the mouse +position, it returns the selected frame for FRAME and nil for X and +Y. */) (void) { struct frame *f; @@ -2578,7 +2586,11 @@ and nil for X and Y. */) &time_dummy); } - XSETFRAME (lispy_dummy, f); + if (f) + XSETFRAME (lispy_dummy, f); + else + lispy_dummy = Qnil; + retval = Fcons (lispy_dummy, Fcons (x, y)); if (!NILP (Vmouse_position_function)) retval = call1 (Vmouse_position_function, retval); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 216b5ee7dd5..94587381424 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3329,8 +3329,8 @@ pgtk_frame_up_to_date (struct frame *f) static void pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window, - enum scroll_bar_part *part, Lisp_Object * x, - Lisp_Object * y, Time * timestamp) + enum scroll_bar_part *part, Lisp_Object *x, + Lisp_Object *y, Time *timestamp) { struct frame *f1; struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); @@ -3339,6 +3339,7 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window, GdkDevice *device; GdkModifierType mask; GdkWindow *win; + bool return_frame_flag = false; block_input (); @@ -3352,30 +3353,37 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window, dpyinfo->last_mouse_scroll_bar = NULL; - if (gui_mouse_grabbed (dpyinfo)) + if (gui_mouse_grabbed (dpyinfo) + && (!EQ (track_mouse, Qdropping) + && !EQ (track_mouse, Qdrag_source))) { - /* 1.1. use last_mouse_frame as frame where the pointer is on. */ + /* 1.1. use last_mouse_frame as frame where the pointer is + on. */ f1 = dpyinfo->last_mouse_frame; } else { f1 = *fp; - /* 1.2. get frame where the pointer is on. */ + /* 1.2. get frame where the pointer is on. */ win = gtk_widget_get_window (FRAME_GTK_WIDGET (*fp)); seat = gdk_display_get_default_seat (dpyinfo->gdpy); device = gdk_seat_get_pointer (seat); - win = - gdk_window_get_device_position (win, device, &win_x, &win_y, &mask); + win = gdk_window_get_device_position (win, device, &win_x, + &win_y, &mask); if (win != NULL) f1 = pgtk_any_window_to_frame (win); else { - /* crossing display server? */ f1 = SELECTED_FRAME (); + + if (!FRAME_PGTK_P (f1)) + f1 = dpyinfo->last_mouse_frame; + + return_frame_flag = EQ (track_mouse, Qdrag_source); } } - /* f1 can be a terminal frame. Bug#50322 */ + /* F1 can be a terminal frame. (Bug#50322) */ if (f1 == NULL || !FRAME_PGTK_P (f1)) { unblock_input (); @@ -3399,7 +3407,7 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window, *bar_window = Qnil; *part = 0; - *fp = f1; + *fp = !return_frame_flag ? f1 : NULL; XSETINT (*x, win_x); XSETINT (*y, win_y); *timestamp = dpyinfo->last_mouse_movement_time;