diff options
| author | Po Lu | 2022-03-26 12:14:52 +0800 |
|---|---|---|
| committer | Po Lu | 2022-03-26 12:14:52 +0800 |
| commit | 98952340bd225d34a0f2f5f32a385dda30e87909 (patch) | |
| tree | 77437c11adb086cf01a07a73bde83b24ebff0782 /src | |
| parent | 66f6324a58a9580f8a3f2f53532838c463581999 (diff) | |
| download | emacs-98952340bd225d34a0f2f5f32a385dda30e87909.tar.gz emacs-98952340bd225d34a0f2f5f32a385dda30e87909.zip | |
Avoid excessive synchronization when initiating drag-and-drop
* src/xterm.c (x_dnd_compute_toplevels): Use XCB to get WM
state, attributes, geometry and to translate coordinates. This
avoids 4 calls to XSync.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 142 |
1 files changed, 138 insertions, 4 deletions
diff --git a/src/xterm.c b/src/xterm.c index deb6d62a27e..e20efd67c79 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -887,12 +887,31 @@ static int | |||
| 887 | x_dnd_compute_toplevels (struct x_display_info *dpyinfo) | 887 | x_dnd_compute_toplevels (struct x_display_info *dpyinfo) |
| 888 | { | 888 | { |
| 889 | Atom type; | 889 | Atom type; |
| 890 | Window *toplevels, child; | 890 | Window *toplevels; |
| 891 | int format, rc, dest_x, dest_y; | 891 | int format, rc; |
| 892 | unsigned long nitems, wmstate_items, bytes_after, *wmstate; | 892 | unsigned long nitems, bytes_after; |
| 893 | unsigned char *data = NULL, *wmstate_data = NULL; | ||
| 894 | unsigned long i; | 893 | unsigned long i; |
| 894 | unsigned char *data = NULL; | ||
| 895 | |||
| 896 | #ifndef USE_XCB | ||
| 897 | int dest_x, dest_y; | ||
| 898 | unsigned long *wmstate; | ||
| 899 | unsigned long wmstate_items; | ||
| 900 | unsigned char *wmstate_data = NULL; | ||
| 895 | XWindowAttributes attrs; | 901 | XWindowAttributes attrs; |
| 902 | Window child; | ||
| 903 | #else | ||
| 904 | uint32_t *wmstate; | ||
| 905 | xcb_get_window_attributes_cookie_t *window_attribute_cookies; | ||
| 906 | xcb_translate_coordinates_cookie_t *translate_coordinate_cookies; | ||
| 907 | xcb_get_property_cookie_t *get_property_cookies; | ||
| 908 | xcb_get_geometry_cookie_t *get_geometry_cookies; | ||
| 909 | xcb_get_window_attributes_reply_t attrs, *attrs_reply; | ||
| 910 | xcb_translate_coordinates_reply_t *coordinates_reply; | ||
| 911 | xcb_get_property_reply_t *property_reply; | ||
| 912 | xcb_get_geometry_reply_t *geometry_reply; | ||
| 913 | xcb_generic_error_t *error; | ||
| 914 | #endif | ||
| 896 | struct x_client_list_window *tem; | 915 | struct x_client_list_window *tem; |
| 897 | #ifdef HAVE_XSHAPE | 916 | #ifdef HAVE_XSHAPE |
| 898 | int count, ordering; | 917 | int count, ordering; |
| @@ -915,10 +934,40 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) | |||
| 915 | 934 | ||
| 916 | toplevels = (Window *) data; | 935 | toplevels = (Window *) data; |
| 917 | 936 | ||
| 937 | #ifdef USE_XCB | ||
| 938 | window_attribute_cookies | ||
| 939 | = alloca (sizeof *window_attribute_cookies * nitems); | ||
| 940 | translate_coordinate_cookies | ||
| 941 | = alloca (sizeof *translate_coordinate_cookies * nitems); | ||
| 942 | get_property_cookies | ||
| 943 | = alloca (sizeof *get_property_cookies * nitems); | ||
| 944 | get_geometry_cookies | ||
| 945 | = alloca (sizeof *get_geometry_cookies * nitems); | ||
| 946 | |||
| 947 | for (i = 0; i < nitems; ++i) | ||
| 948 | { | ||
| 949 | window_attribute_cookies[i] | ||
| 950 | = xcb_get_window_attributes (dpyinfo->xcb_connection, | ||
| 951 | (xcb_window_t) toplevels[i]); | ||
| 952 | translate_coordinate_cookies[i] | ||
| 953 | = xcb_translate_coordinates (dpyinfo->xcb_connection, | ||
| 954 | (xcb_window_t) toplevels[i], | ||
| 955 | (xcb_window_t) dpyinfo->root_window, | ||
| 956 | 0, 0); | ||
| 957 | get_property_cookies[i] | ||
| 958 | = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i], | ||
| 959 | (xcb_atom_t) dpyinfo->Xatom_wm_state, XCB_ATOM_ANY, | ||
| 960 | 0, 2); | ||
| 961 | get_geometry_cookies[i] | ||
| 962 | = xcb_get_geometry (dpyinfo->xcb_connection, (xcb_window_t) toplevels[i]); | ||
| 963 | } | ||
| 964 | #endif | ||
| 965 | |||
| 918 | /* Actually right because _NET_CLIENT_LIST_STACKING has bottom-up | 966 | /* Actually right because _NET_CLIENT_LIST_STACKING has bottom-up |
| 919 | order. */ | 967 | order. */ |
| 920 | for (i = 0; i < nitems; ++i) | 968 | for (i = 0; i < nitems; ++i) |
| 921 | { | 969 | { |
| 970 | #ifndef USE_XCB | ||
| 922 | x_catch_errors (dpyinfo->display); | 971 | x_catch_errors (dpyinfo->display); |
| 923 | rc = (XGetWindowAttributes (dpyinfo->display, | 972 | rc = (XGetWindowAttributes (dpyinfo->display, |
| 924 | toplevels[i], &attrs) | 973 | toplevels[i], &attrs) |
| @@ -941,27 +990,98 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) | |||
| 941 | && !x_had_errors_p (dpyinfo->display) | 990 | && !x_had_errors_p (dpyinfo->display) |
| 942 | && wmstate_data && wmstate_items == 2 && format == 32); | 991 | && wmstate_data && wmstate_items == 2 && format == 32); |
| 943 | x_uncatch_errors_after_check (); | 992 | x_uncatch_errors_after_check (); |
| 993 | #else | ||
| 994 | rc = true; | ||
| 995 | |||
| 996 | attrs_reply | ||
| 997 | = xcb_get_window_attributes_reply (dpyinfo->xcb_connection, | ||
| 998 | window_attribute_cookies[i], | ||
| 999 | &error); | ||
| 1000 | |||
| 1001 | if (!attrs_reply) | ||
| 1002 | { | ||
| 1003 | rc = false; | ||
| 1004 | free (error); | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | coordinates_reply | ||
| 1008 | = xcb_translate_coordinates_reply (dpyinfo->xcb_connection, | ||
| 1009 | translate_coordinate_cookies[i], | ||
| 1010 | &error); | ||
| 1011 | |||
| 1012 | if (!coordinates_reply) | ||
| 1013 | { | ||
| 1014 | rc = false; | ||
| 1015 | free (error); | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | property_reply = xcb_get_property_reply (dpyinfo->xcb_connection, | ||
| 1019 | get_property_cookies[i], | ||
| 1020 | &error); | ||
| 1021 | |||
| 1022 | if (!property_reply) | ||
| 1023 | { | ||
| 1024 | rc = false; | ||
| 1025 | free (error); | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | if (xcb_get_property_value_length (property_reply) != 8 | ||
| 1029 | || property_reply->format != 32) | ||
| 1030 | rc = false; | ||
| 1031 | |||
| 1032 | geometry_reply = xcb_get_geometry_reply (dpyinfo->xcb_connection, | ||
| 1033 | get_geometry_cookies[i], | ||
| 1034 | &error); | ||
| 1035 | |||
| 1036 | if (!geometry_reply) | ||
| 1037 | { | ||
| 1038 | rc = false; | ||
| 1039 | free (error); | ||
| 1040 | } | ||
| 1041 | #endif | ||
| 944 | 1042 | ||
| 945 | if (rc) | 1043 | if (rc) |
| 946 | { | 1044 | { |
| 1045 | #ifdef USE_XCB | ||
| 1046 | wmstate = (uint32_t *) xcb_get_property_value (property_reply); | ||
| 1047 | attrs = *attrs_reply; | ||
| 1048 | #else | ||
| 947 | wmstate = (unsigned long *) wmstate_data; | 1049 | wmstate = (unsigned long *) wmstate_data; |
| 1050 | #endif | ||
| 948 | 1051 | ||
| 949 | tem = xmalloc (sizeof *tem); | 1052 | tem = xmalloc (sizeof *tem); |
| 950 | tem->window = toplevels[i]; | 1053 | tem->window = toplevels[i]; |
| 951 | tem->dpy = dpyinfo->display; | 1054 | tem->dpy = dpyinfo->display; |
| 1055 | #ifndef USE_XCB | ||
| 952 | tem->x = dest_x; | 1056 | tem->x = dest_x; |
| 953 | tem->y = dest_y; | 1057 | tem->y = dest_y; |
| 954 | tem->width = attrs.width + attrs.border_width; | 1058 | tem->width = attrs.width + attrs.border_width; |
| 955 | tem->height = attrs.height + attrs.border_width; | 1059 | tem->height = attrs.height + attrs.border_width; |
| 1060 | #else | ||
| 1061 | tem->x = (coordinates_reply->dst_x | ||
| 1062 | - geometry_reply->border_width); | ||
| 1063 | tem->y = (coordinates_reply->dst_y | ||
| 1064 | - geometry_reply->border_width); | ||
| 1065 | tem->width = (geometry_reply->width | ||
| 1066 | + geometry_reply->border_width); | ||
| 1067 | tem->height = (geometry_reply->height | ||
| 1068 | + geometry_reply->border_width); | ||
| 1069 | #endif | ||
| 956 | tem->mapped_p = (attrs.map_state != IsUnmapped); | 1070 | tem->mapped_p = (attrs.map_state != IsUnmapped); |
| 957 | tem->next = x_dnd_toplevels; | 1071 | tem->next = x_dnd_toplevels; |
| 958 | tem->previous_event_mask = attrs.your_event_mask; | 1072 | tem->previous_event_mask = attrs.your_event_mask; |
| 959 | tem->wm_state = wmstate[0]; | 1073 | tem->wm_state = wmstate[0]; |
| 960 | 1074 | ||
| 1075 | #ifndef USE_XCB | ||
| 961 | XFree (wmstate_data); | 1076 | XFree (wmstate_data); |
| 1077 | #endif | ||
| 962 | 1078 | ||
| 963 | #ifdef HAVE_XSHAPE | 1079 | #ifdef HAVE_XSHAPE |
| 1080 | #ifndef USE_XCB | ||
| 964 | tem->border_width = attrs.border_width; | 1081 | tem->border_width = attrs.border_width; |
| 1082 | #else | ||
| 1083 | tem->border_width = geometry_reply->border_width; | ||
| 1084 | #endif | ||
| 965 | tem->n_bounding_rects = -1; | 1085 | tem->n_bounding_rects = -1; |
| 966 | tem->n_input_rects = -1; | 1086 | tem->n_input_rects = -1; |
| 967 | 1087 | ||
| @@ -1044,6 +1164,20 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) | |||
| 1044 | 1164 | ||
| 1045 | x_dnd_toplevels = tem; | 1165 | x_dnd_toplevels = tem; |
| 1046 | } | 1166 | } |
| 1167 | |||
| 1168 | #ifdef USE_XCB | ||
| 1169 | if (attrs_reply) | ||
| 1170 | free (attrs_reply); | ||
| 1171 | |||
| 1172 | if (coordinates_reply) | ||
| 1173 | free (coordinates_reply); | ||
| 1174 | |||
| 1175 | if (property_reply) | ||
| 1176 | free (property_reply); | ||
| 1177 | |||
| 1178 | if (geometry_reply) | ||
| 1179 | free (geometry_reply); | ||
| 1180 | #endif | ||
| 1047 | } | 1181 | } |
| 1048 | 1182 | ||
| 1049 | return 0; | 1183 | return 0; |