diff options
author | Po Lu <luangruo@yahoo.com> | 2022-04-04 13:42:36 +0800 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2022-04-04 13:42:36 +0800 |
commit | 85fb2341f82d2ba687cefd21ec84d46d06834f57 (patch) | |
tree | fb22a7c6ef9a99d6b39c6a8cef3a4ee098c3d1ca /src | |
parent | 4431cf604736b095aa86fd24da82930c3fc5ce19 (diff) | |
download | emacs-85fb2341f82d2ba687cefd21ec84d46d06834f57.tar.gz emacs-85fb2341f82d2ba687cefd21ec84d46d06834f57.tar.bz2 emacs-85fb2341f82d2ba687cefd21ec84d46d06834f57.zip |
Respect frame extents during drag and drop
* xterm.c (struct x_client_list_window): New fields for frame
extents.
(x_dnd_compute_toplevels): Set window frame extents.
(x_dnd_get_target_window_1): Return None if the mouse is in a
frame extent.
(x_dnd_get_target_window): Likewise.
Diffstat (limited to 'src')
-rw-r--r-- | src/xterm.c | 126 |
1 files changed, 121 insertions, 5 deletions
diff --git a/src/xterm.c b/src/xterm.c index 969be23c7a2..2918b4037f4 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -896,6 +896,11 @@ struct x_client_list_window struct x_client_list_window *next; uint8_t xm_protocol_style; + int frame_extents_left; + int frame_extents_right; + int frame_extents_top; + int frame_extents_bottom; + #ifdef HAVE_XSHAPE int border_width; @@ -1787,27 +1792,30 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) unsigned long nitems, bytes_after; unsigned long i; unsigned char *data = NULL; + int frame_extents[4]; #ifndef USE_XCB int dest_x, dest_y; unsigned long *wmstate; - unsigned long wmstate_items; - unsigned char *wmstate_data = NULL; + unsigned long wmstate_items, extent_items; + unsigned char *wmstate_data = NULL, *extent_data = NULL; XWindowAttributes attrs; Window child; xm_drag_receiver_info xm_info; #else - uint32_t *wmstate; + uint32_t *wmstate, *fextents; uint8_t *xmdata; xcb_get_window_attributes_cookie_t *window_attribute_cookies; xcb_translate_coordinates_cookie_t *translate_coordinate_cookies; xcb_get_property_cookie_t *get_property_cookies; xcb_get_property_cookie_t *xm_property_cookies; + xcb_get_property_cookie_t *extent_property_cookies; xcb_get_geometry_cookie_t *get_geometry_cookies; xcb_get_window_attributes_reply_t attrs, *attrs_reply; xcb_translate_coordinates_reply_t *coordinates_reply; xcb_get_property_reply_t *property_reply; xcb_get_property_reply_t *xm_property_reply; + xcb_get_property_reply_t *extent_property_reply; xcb_get_geometry_reply_t *geometry_reply; xcb_generic_error_t *error; #endif @@ -1855,6 +1863,8 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) = alloca (sizeof *get_property_cookies * nitems); xm_property_cookies = alloca (sizeof *xm_property_cookies * nitems); + extent_property_cookies + = alloca (sizeof *extent_property_cookies * nitems); get_geometry_cookies = alloca (sizeof *get_geometry_cookies * nitems); @@ -1887,6 +1897,11 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO, (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO, 0, 4); + extent_property_cookies[i] + = xcb_get_property (dpyinfo->xcb_connection, 0, + (xcb_window_t) toplevels[i], + (xcb_atom_t) dpyinfo->Xatom_net_frame_extents, + XCB_ATOM_CARDINAL, 0, 4); get_geometry_cookies[i] = xcb_get_geometry (dpyinfo->xcb_connection, (xcb_window_t) toplevels[i]); @@ -1913,6 +1928,11 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) order. */ for (i = 0; i < nitems; ++i) { + frame_extents[0] = 0; + frame_extents[1] = 0; + frame_extents[2] = 0; + frame_extents[3] = 0; + #ifndef USE_XCB x_catch_errors (dpyinfo->display); rc = (XGetWindowAttributes (dpyinfo->display, @@ -1935,6 +1955,24 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) == Success) && !x_had_errors_p (dpyinfo->display) && wmstate_data && wmstate_items == 2 && format == 32); + + if (XGetWindowProperty (dpyinfo->display, toplevels[i], + dpyinfo->Xatom_net_frame_extents, + 0, 4, False, XA_CARDINAL, &type, + &format, &extent_items, &bytes_after, + &extent_data) == Success + && !x_had_errors_p (dpyinfo->display) + && extent_data && extent_items >= 4 && format == 32) + { + frame_extents[0] = ((unsigned long *) extent_data)[0]; + frame_extents[1] = ((unsigned long *) extent_data)[1]; + frame_extents[2] = ((unsigned long *) extent_data)[2]; + frame_extents[3] = ((unsigned long *) extent_data)[3]; + } + + if (extent_data) + XFree (extent_data); + x_uncatch_errors (); #else rc = true; @@ -1971,6 +2009,9 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) free (error); } + /* These requests don't set rc on failure because they aren't + required. */ + xm_property_reply = xcb_get_property_reply (dpyinfo->xcb_connection, xm_property_cookies[i], &error); @@ -1978,6 +2019,28 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) if (!xm_property_reply) free (error); + extent_property_reply = xcb_get_property_reply (dpyinfo->xcb_connection, + extent_property_cookies[i], + &error); + + if (!extent_property_reply) + free (error); + else + { + if (xcb_get_property_value_length (extent_property_reply) == 16 + && extent_property_reply->format == 32 + && extent_property_reply->type == XCB_ATOM_CARDINAL) + { + fextents = xcb_get_property_value (extent_property_reply); + frame_extents[0] = fextents[0]; + frame_extents[1] = fextents[1]; + frame_extents[2] = fextents[2]; + frame_extents[3] = fextents[3]; + } + + free (extent_property_reply); + } + if (property_reply && (xcb_get_property_value_length (property_reply) != 8 || property_reply->format != 32)) @@ -2006,6 +2069,11 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) tem = xmalloc (sizeof *tem); tem->window = toplevels[i]; tem->dpy = dpyinfo->display; + tem->frame_extents_left = frame_extents[0]; + tem->frame_extents_right = frame_extents[1]; + tem->frame_extents_top = frame_extents[2]; + tem->frame_extents_bottom = frame_extents[3]; + #ifndef USE_XCB tem->x = dest_x; tem->y = dest_y; @@ -2387,18 +2455,55 @@ x_dnd_get_target_window_2 (XRectangle *rects, int nrects, static Window x_dnd_get_target_window_1 (struct x_display_info *dpyinfo, - int root_x, int root_y, int *motif_out) + int root_x, int root_y, int *motif_out, + bool *extents_p) { struct x_client_list_window *tem, *chosen = NULL; /* Loop through x_dnd_toplevels until we find the toplevel where root_x and root_y are. */ + *motif_out = XM_DRAG_STYLE_NONE; for (tem = x_dnd_toplevels; tem; tem = tem->next) { if (!tem->mapped_p || tem->wm_state != NormalState) continue; + /* Test if the coordinates are inside the window's frame + extents, and return None in that case. */ + + *extents_p = true; + if (root_x > tem->x - tem->frame_extents_left + && root_x < tem->x + && root_y > tem->y - tem->frame_extents_top + && root_y < (tem->y + tem->height - 1 + + tem->frame_extents_bottom)) + return None; + + if (root_x > tem->x + tem->width + && root_x < (tem->x + tem->width - 1 + + tem->frame_extents_right) + && root_y > tem->y - tem->frame_extents_top + && root_y < (tem->y + tem->height - 1 + + tem->frame_extents_bottom)) + return None; + + if (root_y > tem->y - tem->frame_extents_top + && root_y < tem->y + && root_x > tem->x - tem->frame_extents_left + && root_x < (tem->x + tem->width - 1 + + tem->frame_extents_right)) + return None; + + if (root_y > tem->y + tem->height + && root_y < (tem->y + tem->height - 1 + + tem->frame_extents_bottom) + && root_x >= tem->x - tem->frame_extents_left + && root_x < (tem->x + tem->width - 1 + + tem->frame_extents_right)) + return None; + *extents_p = false; + if (root_x >= tem->x && root_y >= tem->y && root_x < tem->x + tem->width && root_y < tem->y + tem->height) @@ -2566,6 +2671,7 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, { Window child_return, child, dummy, proxy; int dest_x_return, dest_y_return, rc, proto, motif; + bool extents_p; #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2) Window overlay_window; XWindowAttributes attrs; @@ -2581,8 +2687,10 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, if (x_dnd_use_toplevels) { + extents_p = false; child = x_dnd_get_target_window_1 (dpyinfo, root_x, - root_y, motif_out); + root_y, motif_out, + &extents_p); if (!x_dnd_allow_current_frame && FRAME_X_WINDOW (x_dnd_frame) == child) @@ -2613,6 +2721,14 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, return child; } + if (extents_p) + { + *proto_out = -1; + *motif_out = XM_DRAG_STYLE_NONE; + + return None; + } + /* Then look at the composite overlay window. */ #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2) if (dpyinfo->composite_supported_p |