diff options
| author | Po Lu | 2022-10-25 19:50:57 +0800 |
|---|---|---|
| committer | Po Lu | 2022-10-25 19:51:08 +0800 |
| commit | b6097fe279b03e2fb50fc6af063d7c8f1e55fe8b (patch) | |
| tree | 8d7a834c70cbb631fbdb086e9b4a2ba35a6b25c2 | |
| parent | bb95e597a9adcba0080cba85b2270fdf80696b3a (diff) | |
| download | emacs-b6097fe279b03e2fb50fc6af063d7c8f1e55fe8b.tar.gz emacs-b6097fe279b03e2fb50fc6af063d7c8f1e55fe8b.zip | |
Fix drag-and-drop bugs on Lucid build
Also, optimize Fx_translate_coordinates to avoid excessive calls
to _XReply.
* lisp/x-dnd.el (x-dnd-get-drop-rectangle): Return empty drop
rectangle if posn-area.
* src/xfns.c (Fx_translate_coordinates): Accept arg
`require_child'. If not set, allow optimizations based on
cached position data.
* src/xselect.c (x_handle_dnd_message): Use
x_translate_coordinates.
* src/xterm.c (x_translate_coordinates): Export function.
(x_handle_translate_coordinates): New function.
(handle_one_xevent): Fix coding style.
* src/xterm.h: Update prototypes.
| -rw-r--r-- | lisp/x-dnd.el | 10 | ||||
| -rw-r--r-- | src/xfns.c | 24 | ||||
| -rw-r--r-- | src/xselect.c | 7 | ||||
| -rw-r--r-- | src/xterm.c | 30 | ||||
| -rw-r--r-- | src/xterm.h | 4 |
5 files changed, 62 insertions, 13 deletions
diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index ee80e41a22e..058ab99f5cb 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el | |||
| @@ -675,7 +675,15 @@ with coordinates relative to the root window." | |||
| 675 | (defun x-dnd-get-drop-rectangle (window posn) | 675 | (defun x-dnd-get-drop-rectangle (window posn) |
| 676 | "Return the drag-and-drop rectangle at POSN on WINDOW." | 676 | "Return the drag-and-drop rectangle at POSN on WINDOW." |
| 677 | (if (or dnd-scroll-margin | 677 | (if (or dnd-scroll-margin |
| 678 | (not (windowp window))) | 678 | (not (windowp window)) |
| 679 | ;; Drops on the scroll bar aren't allowed, but the mouse | ||
| 680 | ;; rectangle can be set while still on the scroll bar, | ||
| 681 | ;; causing the drag initiator to never send an XdndPosition | ||
| 682 | ;; event that will an XdndStatus message with the accept | ||
| 683 | ;; flag set to be set, even after the mouse enters the | ||
| 684 | ;; window text area. To prevent that, simply don't generate | ||
| 685 | ;; a mouse rectangle when an area is set. | ||
| 686 | (posn-area posn)) | ||
| 679 | '(0 0 0 0) | 687 | '(0 0 0 0) |
| 680 | (let ((window-rectangle (x-dnd-get-window-rectangle window)) | 688 | (let ((window-rectangle (x-dnd-get-window-rectangle window)) |
| 681 | object-rectangle) | 689 | object-rectangle) |
diff --git a/src/xfns.c b/src/xfns.c index e8732986eb9..3ff7a8c2865 100644 --- a/src/xfns.c +++ b/src/xfns.c | |||
| @@ -7913,7 +7913,7 @@ Otherwise, the return value is a vector with the following fields: | |||
| 7913 | 7913 | ||
| 7914 | DEFUN ("x-translate-coordinates", Fx_translate_coordinates, | 7914 | DEFUN ("x-translate-coordinates", Fx_translate_coordinates, |
| 7915 | Sx_translate_coordinates, | 7915 | Sx_translate_coordinates, |
| 7916 | 1, 5, 0, doc: /* Translate coordinates from FRAME. | 7916 | 1, 6, 0, doc: /* Translate coordinates from FRAME. |
| 7917 | Translate the given coordinates SOURCE-X and SOURCE-Y from | 7917 | Translate the given coordinates SOURCE-X and SOURCE-Y from |
| 7918 | SOURCE-WINDOW's coordinate space to that of DEST-WINDOW, on FRAME. | 7918 | SOURCE-WINDOW's coordinate space to that of DEST-WINDOW, on FRAME. |
| 7919 | 7919 | ||
| @@ -7929,16 +7929,21 @@ Return a list of (X Y CHILD) if the given coordinates are on the same | |||
| 7929 | screen, or nil otherwise, where X and Y are the coordinates in | 7929 | screen, or nil otherwise, where X and Y are the coordinates in |
| 7930 | DEST-WINDOW's coordinate space, and CHILD is the window ID of any | 7930 | DEST-WINDOW's coordinate space, and CHILD is the window ID of any |
| 7931 | mapped child in DEST-WINDOW at those coordinates, or nil if there is | 7931 | mapped child in DEST-WINDOW at those coordinates, or nil if there is |
| 7932 | no such window. */) | 7932 | no such window. If REQUIRE-CHILD is nil, avoid fetching CHILD if it |
| 7933 | would result in an avoidable request to the X server, thereby | ||
| 7934 | improving performance when the X connection is over a slow network. | ||
| 7935 | Otherwise, always obtain the mapped child window from the X | ||
| 7936 | server. */) | ||
| 7933 | (Lisp_Object frame, Lisp_Object source_window, | 7937 | (Lisp_Object frame, Lisp_Object source_window, |
| 7934 | Lisp_Object dest_window, Lisp_Object source_x, | 7938 | Lisp_Object dest_window, Lisp_Object source_x, |
| 7935 | Lisp_Object source_y) | 7939 | Lisp_Object source_y, Lisp_Object require_child) |
| 7936 | { | 7940 | { |
| 7937 | struct x_display_info *dpyinfo; | 7941 | struct x_display_info *dpyinfo; |
| 7938 | struct frame *source_frame; | 7942 | struct frame *source_frame; |
| 7939 | int dest_x, dest_y; | 7943 | int dest_x, dest_y; |
| 7940 | Window child_return, src, dest; | 7944 | Window child_return, src, dest; |
| 7941 | Bool rc; | 7945 | Bool rc; |
| 7946 | Lisp_Object temp_result; | ||
| 7942 | 7947 | ||
| 7943 | dpyinfo = check_x_display_info (frame); | 7948 | dpyinfo = check_x_display_info (frame); |
| 7944 | dest_x = 0; | 7949 | dest_x = 0; |
| @@ -7956,6 +7961,8 @@ no such window. */) | |||
| 7956 | dest_y = XFIXNUM (source_y); | 7961 | dest_y = XFIXNUM (source_y); |
| 7957 | } | 7962 | } |
| 7958 | 7963 | ||
| 7964 | source_frame = NULL; | ||
| 7965 | |||
| 7959 | if (!NILP (source_window)) | 7966 | if (!NILP (source_window)) |
| 7960 | CONS_TO_INTEGER (source_window, Window, src); | 7967 | CONS_TO_INTEGER (source_window, Window, src); |
| 7961 | else | 7968 | else |
| @@ -7964,6 +7971,17 @@ no such window. */) | |||
| 7964 | src = FRAME_X_WINDOW (source_frame); | 7971 | src = FRAME_X_WINDOW (source_frame); |
| 7965 | } | 7972 | } |
| 7966 | 7973 | ||
| 7974 | /* If require_child is nil, try to avoid an avoidable roundtrip to | ||
| 7975 | the X server. */ | ||
| 7976 | if (NILP (require_child) && source_frame) | ||
| 7977 | { | ||
| 7978 | temp_result | ||
| 7979 | = x_handle_translate_coordinates (source_frame, dest_window, dest_x, | ||
| 7980 | dest_y); | ||
| 7981 | if (!NILP (temp_result)) | ||
| 7982 | return temp_result; | ||
| 7983 | } | ||
| 7984 | |||
| 7967 | if (!src) | 7985 | if (!src) |
| 7968 | src = dpyinfo->root_window; | 7986 | src = dpyinfo->root_window; |
| 7969 | 7987 | ||
diff --git a/src/xselect.c b/src/xselect.c index 498c28af536..db5c7853e7f 100644 --- a/src/xselect.c +++ b/src/xselect.c | |||
| @@ -2787,7 +2787,6 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event, | |||
| 2787 | unsigned char *data = (unsigned char *) event->data.b; | 2787 | unsigned char *data = (unsigned char *) event->data.b; |
| 2788 | int idata[5]; | 2788 | int idata[5]; |
| 2789 | ptrdiff_t i; | 2789 | ptrdiff_t i; |
| 2790 | Window child_return; | ||
| 2791 | 2790 | ||
| 2792 | for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i) | 2791 | for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i) |
| 2793 | if (dpyinfo->x_dnd_atoms[i] == event->message_type) break; | 2792 | if (dpyinfo->x_dnd_atoms[i] == event->message_type) break; |
| @@ -2822,11 +2821,7 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event, | |||
| 2822 | if (!root_window_coords) | 2821 | if (!root_window_coords) |
| 2823 | x_relative_mouse_position (f, &x, &y); | 2822 | x_relative_mouse_position (f, &x, &y); |
| 2824 | else | 2823 | else |
| 2825 | XTranslateCoordinates (dpyinfo->display, | 2824 | x_translate_coordinates (f, root_x, root_y, &x, &y); |
| 2826 | dpyinfo->root_window, | ||
| 2827 | FRAME_X_WINDOW (f), | ||
| 2828 | root_x, root_y, | ||
| 2829 | &x, &y, &child_return); | ||
| 2830 | 2825 | ||
| 2831 | bufp->kind = DRAG_N_DROP_EVENT; | 2826 | bufp->kind = DRAG_N_DROP_EVENT; |
| 2832 | bufp->frame_or_window = frame; | 2827 | bufp->frame_or_window = frame; |
diff --git a/src/xterm.c b/src/xterm.c index 205c948c461..b061383a2ea 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -1143,7 +1143,6 @@ static Window x_get_window_below (Display *, Window, int, int, int *, int *); | |||
| 1143 | #ifndef USE_TOOLKIT_SCROLL_BARS | 1143 | #ifndef USE_TOOLKIT_SCROLL_BARS |
| 1144 | static void x_scroll_bar_redraw (struct scroll_bar *); | 1144 | static void x_scroll_bar_redraw (struct scroll_bar *); |
| 1145 | #endif | 1145 | #endif |
| 1146 | static void x_translate_coordinates (struct frame *, int, int, int *, int *); | ||
| 1147 | 1146 | ||
| 1148 | /* Global state maintained during a drag-and-drop operation. */ | 1147 | /* Global state maintained during a drag-and-drop operation. */ |
| 1149 | 1148 | ||
| @@ -13658,7 +13657,7 @@ x_compute_root_window_offset (struct frame *f, int root_x, int root_y, | |||
| 13658 | many cases while handling events, which would otherwise result in | 13657 | many cases while handling events, which would otherwise result in |
| 13659 | slowdowns over slow network connections. */ | 13658 | slowdowns over slow network connections. */ |
| 13660 | 13659 | ||
| 13661 | static void | 13660 | void |
| 13662 | x_translate_coordinates (struct frame *f, int root_x, int root_y, | 13661 | x_translate_coordinates (struct frame *f, int root_x, int root_y, |
| 13663 | int *x_out, int *y_out) | 13662 | int *x_out, int *y_out) |
| 13664 | { | 13663 | { |
| @@ -13731,6 +13730,31 @@ x_translate_coordinates_to_root (struct frame *f, int x, int y, | |||
| 13731 | } | 13730 | } |
| 13732 | } | 13731 | } |
| 13733 | 13732 | ||
| 13733 | /* Do x-translate-coordinates, but try to avoid a roundtrip to the X | ||
| 13734 | server at the cost of not returning `child', which most callers | ||
| 13735 | have no reason to use. */ | ||
| 13736 | |||
| 13737 | Lisp_Object | ||
| 13738 | x_handle_translate_coordinates (struct frame *f, Lisp_Object dest_window, | ||
| 13739 | int source_x, int source_y) | ||
| 13740 | { | ||
| 13741 | if (NILP (dest_window)) | ||
| 13742 | { | ||
| 13743 | /* We are translating coordinates from a frame to the root | ||
| 13744 | window. Avoid a roundtrip if possible by using cached | ||
| 13745 | coordinates. */ | ||
| 13746 | |||
| 13747 | if (!FRAME_X_OUTPUT (f)->window_offset_certain_p) | ||
| 13748 | return Qnil; | ||
| 13749 | |||
| 13750 | return list3 (make_fixnum (source_x + FRAME_X_OUTPUT (f)->root_x), | ||
| 13751 | make_fixnum (source_y + FRAME_X_OUTPUT (f)->root_y), | ||
| 13752 | Qnil); | ||
| 13753 | } | ||
| 13754 | |||
| 13755 | return Qnil; | ||
| 13756 | } | ||
| 13757 | |||
| 13734 | /* The same, but for an XIDeviceEvent. */ | 13758 | /* The same, but for an XIDeviceEvent. */ |
| 13735 | 13759 | ||
| 13736 | #ifdef HAVE_XINPUT2 | 13760 | #ifdef HAVE_XINPUT2 |
| @@ -20826,7 +20850,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 20826 | event->xbutton.time); | 20850 | event->xbutton.time); |
| 20827 | } | 20851 | } |
| 20828 | else if (x_dnd_last_seen_window != None | 20852 | else if (x_dnd_last_seen_window != None |
| 20829 | && x_dnd_last_protocol_version != -1) | 20853 | && x_dnd_last_protocol_version != -1) |
| 20830 | { | 20854 | { |
| 20831 | x_dnd_pending_finish_target = x_dnd_last_seen_toplevel; | 20855 | x_dnd_pending_finish_target = x_dnd_last_seen_toplevel; |
| 20832 | x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version; | 20856 | x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version; |
diff --git a/src/xterm.h b/src/xterm.h index 2967d105ea2..537cabc9577 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -1695,8 +1695,12 @@ extern void x_xr_apply_ext_clip (struct frame *, GC); | |||
| 1695 | extern void x_xr_reset_ext_clip (struct frame *); | 1695 | extern void x_xr_reset_ext_clip (struct frame *); |
| 1696 | #endif | 1696 | #endif |
| 1697 | 1697 | ||
| 1698 | extern void x_translate_coordinates (struct frame *, int, int, int *, int *); | ||
| 1698 | extern void x_translate_coordinates_to_root (struct frame *, int, int, | 1699 | extern void x_translate_coordinates_to_root (struct frame *, int, int, |
| 1699 | int *, int *); | 1700 | int *, int *); |
| 1701 | extern Lisp_Object x_handle_translate_coordinates (struct frame *, Lisp_Object, | ||
| 1702 | int, int); | ||
| 1703 | |||
| 1700 | extern Bool x_query_pointer (Display *, Window, Window *, Window *, int *, | 1704 | extern Bool x_query_pointer (Display *, Window, Window *, Window *, int *, |
| 1701 | int *, int *, int *, unsigned int *); | 1705 | int *, int *, int *, unsigned int *); |
| 1702 | 1706 | ||