diff options
| author | Po Lu | 2022-04-04 13:42:36 +0800 |
|---|---|---|
| committer | Po Lu | 2022-04-04 13:42:36 +0800 |
| commit | 85fb2341f82d2ba687cefd21ec84d46d06834f57 (patch) | |
| tree | fb22a7c6ef9a99d6b39c6a8cef3a4ee098c3d1ca /src | |
| parent | 4431cf604736b095aa86fd24da82930c3fc5ce19 (diff) | |
| download | emacs-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.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 | |||
| 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 | ||
| 2388 | static Window | 2456 | static Window |
| 2389 | x_dnd_get_target_window_1 (struct x_display_info *dpyinfo, | 2457 | x_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 |