aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-04-04 13:42:36 +0800
committerPo Lu2022-04-04 13:42:36 +0800
commit85fb2341f82d2ba687cefd21ec84d46d06834f57 (patch)
treefb22a7c6ef9a99d6b39c6a8cef3a4ee098c3d1ca /src
parent4431cf604736b095aa86fd24da82930c3fc5ce19 (diff)
downloademacs-85fb2341f82d2ba687cefd21ec84d46d06834f57.tar.gz
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.c126
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
896 struct x_client_list_window *next; 896 struct x_client_list_window *next;
897 uint8_t xm_protocol_style; 897 uint8_t xm_protocol_style;
898 898
899 int frame_extents_left;
900 int frame_extents_right;
901 int frame_extents_top;
902 int frame_extents_bottom;
903
899#ifdef HAVE_XSHAPE 904#ifdef HAVE_XSHAPE
900 int border_width; 905 int border_width;
901 906
@@ -1787,27 +1792,30 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
1787 unsigned long nitems, bytes_after; 1792 unsigned long nitems, bytes_after;
1788 unsigned long i; 1793 unsigned long i;
1789 unsigned char *data = NULL; 1794 unsigned char *data = NULL;
1795 int frame_extents[4];
1790 1796
1791#ifndef USE_XCB 1797#ifndef USE_XCB
1792 int dest_x, dest_y; 1798 int dest_x, dest_y;
1793 unsigned long *wmstate; 1799 unsigned long *wmstate;
1794 unsigned long wmstate_items; 1800 unsigned long wmstate_items, extent_items;
1795 unsigned char *wmstate_data = NULL; 1801 unsigned char *wmstate_data = NULL, *extent_data = NULL;
1796 XWindowAttributes attrs; 1802 XWindowAttributes attrs;
1797 Window child; 1803 Window child;
1798 xm_drag_receiver_info xm_info; 1804 xm_drag_receiver_info xm_info;
1799#else 1805#else
1800 uint32_t *wmstate; 1806 uint32_t *wmstate, *fextents;
1801 uint8_t *xmdata; 1807 uint8_t *xmdata;
1802 xcb_get_window_attributes_cookie_t *window_attribute_cookies; 1808 xcb_get_window_attributes_cookie_t *window_attribute_cookies;
1803 xcb_translate_coordinates_cookie_t *translate_coordinate_cookies; 1809 xcb_translate_coordinates_cookie_t *translate_coordinate_cookies;
1804 xcb_get_property_cookie_t *get_property_cookies; 1810 xcb_get_property_cookie_t *get_property_cookies;
1805 xcb_get_property_cookie_t *xm_property_cookies; 1811 xcb_get_property_cookie_t *xm_property_cookies;
1812 xcb_get_property_cookie_t *extent_property_cookies;
1806 xcb_get_geometry_cookie_t *get_geometry_cookies; 1813 xcb_get_geometry_cookie_t *get_geometry_cookies;
1807 xcb_get_window_attributes_reply_t attrs, *attrs_reply; 1814 xcb_get_window_attributes_reply_t attrs, *attrs_reply;
1808 xcb_translate_coordinates_reply_t *coordinates_reply; 1815 xcb_translate_coordinates_reply_t *coordinates_reply;
1809 xcb_get_property_reply_t *property_reply; 1816 xcb_get_property_reply_t *property_reply;
1810 xcb_get_property_reply_t *xm_property_reply; 1817 xcb_get_property_reply_t *xm_property_reply;
1818 xcb_get_property_reply_t *extent_property_reply;
1811 xcb_get_geometry_reply_t *geometry_reply; 1819 xcb_get_geometry_reply_t *geometry_reply;
1812 xcb_generic_error_t *error; 1820 xcb_generic_error_t *error;
1813#endif 1821#endif
@@ -1855,6 +1863,8 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
1855 = alloca (sizeof *get_property_cookies * nitems); 1863 = alloca (sizeof *get_property_cookies * nitems);
1856 xm_property_cookies 1864 xm_property_cookies
1857 = alloca (sizeof *xm_property_cookies * nitems); 1865 = alloca (sizeof *xm_property_cookies * nitems);
1866 extent_property_cookies
1867 = alloca (sizeof *extent_property_cookies * nitems);
1858 get_geometry_cookies 1868 get_geometry_cookies
1859 = alloca (sizeof *get_geometry_cookies * nitems); 1869 = alloca (sizeof *get_geometry_cookies * nitems);
1860 1870
@@ -1887,6 +1897,11 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
1887 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO, 1897 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
1888 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO, 1898 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
1889 0, 4); 1899 0, 4);
1900 extent_property_cookies[i]
1901 = xcb_get_property (dpyinfo->xcb_connection, 0,
1902 (xcb_window_t) toplevels[i],
1903 (xcb_atom_t) dpyinfo->Xatom_net_frame_extents,
1904 XCB_ATOM_CARDINAL, 0, 4);
1890 get_geometry_cookies[i] 1905 get_geometry_cookies[i]
1891 = xcb_get_geometry (dpyinfo->xcb_connection, (xcb_window_t) toplevels[i]); 1906 = xcb_get_geometry (dpyinfo->xcb_connection, (xcb_window_t) toplevels[i]);
1892 1907
@@ -1913,6 +1928,11 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
1913 order. */ 1928 order. */
1914 for (i = 0; i < nitems; ++i) 1929 for (i = 0; i < nitems; ++i)
1915 { 1930 {
1931 frame_extents[0] = 0;
1932 frame_extents[1] = 0;
1933 frame_extents[2] = 0;
1934 frame_extents[3] = 0;
1935
1916#ifndef USE_XCB 1936#ifndef USE_XCB
1917 x_catch_errors (dpyinfo->display); 1937 x_catch_errors (dpyinfo->display);
1918 rc = (XGetWindowAttributes (dpyinfo->display, 1938 rc = (XGetWindowAttributes (dpyinfo->display,
@@ -1935,6 +1955,24 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
1935 == Success) 1955 == Success)
1936 && !x_had_errors_p (dpyinfo->display) 1956 && !x_had_errors_p (dpyinfo->display)
1937 && wmstate_data && wmstate_items == 2 && format == 32); 1957 && wmstate_data && wmstate_items == 2 && format == 32);
1958
1959 if (XGetWindowProperty (dpyinfo->display, toplevels[i],
1960 dpyinfo->Xatom_net_frame_extents,
1961 0, 4, False, XA_CARDINAL, &type,
1962 &format, &extent_items, &bytes_after,
1963 &extent_data) == Success
1964 && !x_had_errors_p (dpyinfo->display)
1965 && extent_data && extent_items >= 4 && format == 32)
1966 {
1967 frame_extents[0] = ((unsigned long *) extent_data)[0];
1968 frame_extents[1] = ((unsigned long *) extent_data)[1];
1969 frame_extents[2] = ((unsigned long *) extent_data)[2];
1970 frame_extents[3] = ((unsigned long *) extent_data)[3];
1971 }
1972
1973 if (extent_data)
1974 XFree (extent_data);
1975
1938 x_uncatch_errors (); 1976 x_uncatch_errors ();
1939#else 1977#else
1940 rc = true; 1978 rc = true;
@@ -1971,6 +2009,9 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
1971 free (error); 2009 free (error);
1972 } 2010 }
1973 2011
2012 /* These requests don't set rc on failure because they aren't
2013 required. */
2014
1974 xm_property_reply = xcb_get_property_reply (dpyinfo->xcb_connection, 2015 xm_property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
1975 xm_property_cookies[i], 2016 xm_property_cookies[i],
1976 &error); 2017 &error);
@@ -1978,6 +2019,28 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
1978 if (!xm_property_reply) 2019 if (!xm_property_reply)
1979 free (error); 2020 free (error);
1980 2021
2022 extent_property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
2023 extent_property_cookies[i],
2024 &error);
2025
2026 if (!extent_property_reply)
2027 free (error);
2028 else
2029 {
2030 if (xcb_get_property_value_length (extent_property_reply) == 16
2031 && extent_property_reply->format == 32
2032 && extent_property_reply->type == XCB_ATOM_CARDINAL)
2033 {
2034 fextents = xcb_get_property_value (extent_property_reply);
2035 frame_extents[0] = fextents[0];
2036 frame_extents[1] = fextents[1];
2037 frame_extents[2] = fextents[2];
2038 frame_extents[3] = fextents[3];
2039 }
2040
2041 free (extent_property_reply);
2042 }
2043
1981 if (property_reply 2044 if (property_reply
1982 && (xcb_get_property_value_length (property_reply) != 8 2045 && (xcb_get_property_value_length (property_reply) != 8
1983 || property_reply->format != 32)) 2046 || property_reply->format != 32))
@@ -2006,6 +2069,11 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
2006 tem = xmalloc (sizeof *tem); 2069 tem = xmalloc (sizeof *tem);
2007 tem->window = toplevels[i]; 2070 tem->window = toplevels[i];
2008 tem->dpy = dpyinfo->display; 2071 tem->dpy = dpyinfo->display;
2072 tem->frame_extents_left = frame_extents[0];
2073 tem->frame_extents_right = frame_extents[1];
2074 tem->frame_extents_top = frame_extents[2];
2075 tem->frame_extents_bottom = frame_extents[3];
2076
2009#ifndef USE_XCB 2077#ifndef USE_XCB
2010 tem->x = dest_x; 2078 tem->x = dest_x;
2011 tem->y = dest_y; 2079 tem->y = dest_y;
@@ -2387,18 +2455,55 @@ x_dnd_get_target_window_2 (XRectangle *rects, int nrects,
2387 2455
2388static Window 2456static Window
2389x_dnd_get_target_window_1 (struct x_display_info *dpyinfo, 2457x_dnd_get_target_window_1 (struct x_display_info *dpyinfo,
2390 int root_x, int root_y, int *motif_out) 2458 int root_x, int root_y, int *motif_out,
2459 bool *extents_p)
2391{ 2460{
2392 struct x_client_list_window *tem, *chosen = NULL; 2461 struct x_client_list_window *tem, *chosen = NULL;
2393 2462
2394 /* Loop through x_dnd_toplevels until we find the toplevel where 2463 /* Loop through x_dnd_toplevels until we find the toplevel where
2395 root_x and root_y are. */ 2464 root_x and root_y are. */
2396 2465
2466 *motif_out = XM_DRAG_STYLE_NONE;
2397 for (tem = x_dnd_toplevels; tem; tem = tem->next) 2467 for (tem = x_dnd_toplevels; tem; tem = tem->next)
2398 { 2468 {
2399 if (!tem->mapped_p || tem->wm_state != NormalState) 2469 if (!tem->mapped_p || tem->wm_state != NormalState)
2400 continue; 2470 continue;
2401 2471
2472 /* Test if the coordinates are inside the window's frame
2473 extents, and return None in that case. */
2474
2475 *extents_p = true;
2476 if (root_x > tem->x - tem->frame_extents_left
2477 && root_x < tem->x
2478 && root_y > tem->y - tem->frame_extents_top
2479 && root_y < (tem->y + tem->height - 1
2480 + tem->frame_extents_bottom))
2481 return None;
2482
2483 if (root_x > tem->x + tem->width
2484 && root_x < (tem->x + tem->width - 1
2485 + tem->frame_extents_right)
2486 && root_y > tem->y - tem->frame_extents_top
2487 && root_y < (tem->y + tem->height - 1
2488 + tem->frame_extents_bottom))
2489 return None;
2490
2491 if (root_y > tem->y - tem->frame_extents_top
2492 && root_y < tem->y
2493 && root_x > tem->x - tem->frame_extents_left
2494 && root_x < (tem->x + tem->width - 1
2495 + tem->frame_extents_right))
2496 return None;
2497
2498 if (root_y > tem->y + tem->height
2499 && root_y < (tem->y + tem->height - 1
2500 + tem->frame_extents_bottom)
2501 && root_x >= tem->x - tem->frame_extents_left
2502 && root_x < (tem->x + tem->width - 1
2503 + tem->frame_extents_right))
2504 return None;
2505 *extents_p = false;
2506
2402 if (root_x >= tem->x && root_y >= tem->y 2507 if (root_x >= tem->x && root_y >= tem->y
2403 && root_x < tem->x + tem->width 2508 && root_x < tem->x + tem->width
2404 && root_y < tem->y + tem->height) 2509 && root_y < tem->y + tem->height)
@@ -2566,6 +2671,7 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo,
2566{ 2671{
2567 Window child_return, child, dummy, proxy; 2672 Window child_return, child, dummy, proxy;
2568 int dest_x_return, dest_y_return, rc, proto, motif; 2673 int dest_x_return, dest_y_return, rc, proto, motif;
2674 bool extents_p;
2569#if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2) 2675#if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
2570 Window overlay_window; 2676 Window overlay_window;
2571 XWindowAttributes attrs; 2677 XWindowAttributes attrs;
@@ -2581,8 +2687,10 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo,
2581 2687
2582 if (x_dnd_use_toplevels) 2688 if (x_dnd_use_toplevels)
2583 { 2689 {
2690 extents_p = false;
2584 child = x_dnd_get_target_window_1 (dpyinfo, root_x, 2691 child = x_dnd_get_target_window_1 (dpyinfo, root_x,
2585 root_y, motif_out); 2692 root_y, motif_out,
2693 &extents_p);
2586 2694
2587 if (!x_dnd_allow_current_frame 2695 if (!x_dnd_allow_current_frame
2588 && FRAME_X_WINDOW (x_dnd_frame) == child) 2696 && FRAME_X_WINDOW (x_dnd_frame) == child)
@@ -2613,6 +2721,14 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo,
2613 return child; 2721 return child;
2614 } 2722 }
2615 2723
2724 if (extents_p)
2725 {
2726 *proto_out = -1;
2727 *motif_out = XM_DRAG_STYLE_NONE;
2728
2729 return None;
2730 }
2731
2616 /* Then look at the composite overlay window. */ 2732 /* Then look at the composite overlay window. */
2617#if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2) 2733#if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
2618 if (dpyinfo->composite_supported_p 2734 if (dpyinfo->composite_supported_p