diff options
| author | Po Lu | 2022-03-20 09:53:52 +0800 |
|---|---|---|
| committer | Po Lu | 2022-03-20 09:53:52 +0800 |
| commit | 77f5eb874b70ab78ca4daf3adf30f18d002db439 (patch) | |
| tree | dec5e7d164ef4565af0ade2be1c9852982e7e24e /src | |
| parent | d2ac7447db52f492f9cbb52566de2e452c8bc65d (diff) | |
| download | emacs-77f5eb874b70ab78ca4daf3adf30f18d002db439.tar.gz emacs-77f5eb874b70ab78ca4daf3adf30f18d002db439.zip | |
Improve behaviour of drag-n-drop during window manager operations
* src/xterm.c (x_dnd_begin_drag_and_drop): Select for some
events on the root window.
(x_dnd_update_state): New function.
(handle_one_xevent): Call that function when we get some events
from the root window substructure or the window manager.
(x_term_init): New atom `_NET_CLIENT_LIST_STACKING'.
* src/xterm.h (struct x_display_info): New atom
`_NET_CLIENT_LIST_STACKING'.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 107 | ||||
| -rw-r--r-- | src/xterm.h | 2 |
2 files changed, 108 insertions, 1 deletions
diff --git a/src/xterm.c b/src/xterm.c index 4f8accbda3a..3e888407b3b 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -1149,6 +1149,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 1149 | #ifdef HAVE_X_I18N | 1149 | #ifdef HAVE_X_I18N |
| 1150 | XIC ic = FRAME_XIC (f); | 1150 | XIC ic = FRAME_XIC (f); |
| 1151 | #endif | 1151 | #endif |
| 1152 | XWindowAttributes root_window_attrs; | ||
| 1152 | 1153 | ||
| 1153 | struct input_event hold_quit; | 1154 | struct input_event hold_quit; |
| 1154 | char *atom_name; | 1155 | char *atom_name; |
| @@ -1187,7 +1188,21 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 1187 | current_count = 0; | 1188 | current_count = 0; |
| 1188 | #endif | 1189 | #endif |
| 1189 | 1190 | ||
| 1191 | /* Now select for SubstructureNotifyMask and PropertyNotifyMask on | ||
| 1192 | the root window, so we can get notified when window stacking | ||
| 1193 | changes, a common operation during drag-and-drop. */ | ||
| 1194 | |||
| 1190 | block_input (); | 1195 | block_input (); |
| 1196 | XGetWindowAttributes (FRAME_X_DISPLAY (f), | ||
| 1197 | FRAME_DISPLAY_INFO (f)->root_window, | ||
| 1198 | &root_window_attrs); | ||
| 1199 | |||
| 1200 | XSelectInput (FRAME_X_DISPLAY (f), | ||
| 1201 | FRAME_DISPLAY_INFO (f)->root_window, | ||
| 1202 | root_window_attrs.your_event_mask | ||
| 1203 | | SubstructureNotifyMask | ||
| 1204 | | PropertyChangeMask); | ||
| 1205 | |||
| 1191 | #ifdef HAVE_X_I18N | 1206 | #ifdef HAVE_X_I18N |
| 1192 | /* Make sure no events get filtered when XInput 2 is enabled. | 1207 | /* Make sure no events get filtered when XInput 2 is enabled. |
| 1193 | Otherwise, the ibus XIM server gets very confused. */ | 1208 | Otherwise, the ibus XIM server gets very confused. */ |
| @@ -1230,6 +1245,10 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 1230 | #ifdef HAVE_X_I18N | 1245 | #ifdef HAVE_X_I18N |
| 1231 | FRAME_XIC (f) = ic; | 1246 | FRAME_XIC (f) = ic; |
| 1232 | #endif | 1247 | #endif |
| 1248 | /* Restore the old event mask. */ | ||
| 1249 | XSelectInput (FRAME_X_DISPLAY (f), | ||
| 1250 | FRAME_DISPLAY_INFO (f)->root_window, | ||
| 1251 | root_window_attrs.your_event_mask); | ||
| 1233 | unblock_input (); | 1252 | unblock_input (); |
| 1234 | quit (); | 1253 | quit (); |
| 1235 | } | 1254 | } |
| @@ -1243,6 +1262,11 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 1243 | current_hold_quit = NULL; | 1262 | current_hold_quit = NULL; |
| 1244 | #endif | 1263 | #endif |
| 1245 | 1264 | ||
| 1265 | /* Restore the old event mask. */ | ||
| 1266 | XSelectInput (FRAME_X_DISPLAY (f), | ||
| 1267 | FRAME_DISPLAY_INFO (f)->root_window, | ||
| 1268 | root_window_attrs.your_event_mask); | ||
| 1269 | |||
| 1246 | unblock_input (); | 1270 | unblock_input (); |
| 1247 | 1271 | ||
| 1248 | if (x_dnd_return_frame == 3) | 1272 | if (x_dnd_return_frame == 3) |
| @@ -10566,6 +10590,74 @@ mouse_or_wdesc_frame (struct x_display_info *dpyinfo, int wdesc) | |||
| 10566 | } | 10590 | } |
| 10567 | } | 10591 | } |
| 10568 | 10592 | ||
| 10593 | /* Get the window underneath the pointer, see if it moved, and update | ||
| 10594 | the DND state accordingly. */ | ||
| 10595 | static void | ||
| 10596 | x_dnd_update_state (struct x_display_info *dpyinfo) | ||
| 10597 | { | ||
| 10598 | int root_x, root_y, dummy_x, dummy_y, target_proto; | ||
| 10599 | unsigned int dummy_mask; | ||
| 10600 | Window dummy, dummy_child, target; | ||
| 10601 | |||
| 10602 | puts ("us"); | ||
| 10603 | |||
| 10604 | if (XQueryPointer (dpyinfo->display, | ||
| 10605 | dpyinfo->root_window, | ||
| 10606 | &dummy, &dummy_child, | ||
| 10607 | &root_x, &root_y, | ||
| 10608 | &dummy_x, &dummy_y, | ||
| 10609 | &dummy_mask)) | ||
| 10610 | { | ||
| 10611 | target = x_dnd_get_target_window (dpyinfo, root_x, | ||
| 10612 | root_y, &target_proto); | ||
| 10613 | |||
| 10614 | if (target != x_dnd_last_seen_window) | ||
| 10615 | { | ||
| 10616 | if (x_dnd_last_seen_window != None | ||
| 10617 | && x_dnd_last_protocol_version != -1 | ||
| 10618 | && x_dnd_last_seen_window != FRAME_X_WINDOW (x_dnd_frame)) | ||
| 10619 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); | ||
| 10620 | |||
| 10621 | if (x_dnd_last_seen_window == FRAME_X_WINDOW (x_dnd_frame) | ||
| 10622 | && x_dnd_return_frame == 1) | ||
| 10623 | x_dnd_return_frame = 2; | ||
| 10624 | |||
| 10625 | if (x_dnd_return_frame == 2 | ||
| 10626 | && x_any_window_to_frame (dpyinfo, target)) | ||
| 10627 | { | ||
| 10628 | x_dnd_in_progress = false; | ||
| 10629 | x_dnd_return_frame_object | ||
| 10630 | = x_any_window_to_frame (dpyinfo, target); | ||
| 10631 | x_dnd_return_frame = 3; | ||
| 10632 | } | ||
| 10633 | |||
| 10634 | x_dnd_last_seen_window = target; | ||
| 10635 | x_dnd_last_protocol_version = target_proto; | ||
| 10636 | |||
| 10637 | if (target != None && x_dnd_last_protocol_version != -1) | ||
| 10638 | x_dnd_send_enter (x_dnd_frame, target, | ||
| 10639 | x_dnd_last_protocol_version); | ||
| 10640 | } | ||
| 10641 | |||
| 10642 | if (x_dnd_last_protocol_version != -1 && target != None) | ||
| 10643 | x_dnd_send_position (x_dnd_frame, target, | ||
| 10644 | x_dnd_last_protocol_version, | ||
| 10645 | root_x, root_y, x_dnd_selection_timestamp, | ||
| 10646 | dpyinfo->Xatom_XdndActionCopy); | ||
| 10647 | } | ||
| 10648 | /* The pointer moved out of the screen. */ | ||
| 10649 | else if (x_dnd_last_protocol_version) | ||
| 10650 | { | ||
| 10651 | if (x_dnd_last_seen_window != None | ||
| 10652 | && x_dnd_last_protocol_version != -1) | ||
| 10653 | x_dnd_send_leave (x_dnd_frame, | ||
| 10654 | x_dnd_last_seen_window); | ||
| 10655 | |||
| 10656 | x_dnd_in_progress = false; | ||
| 10657 | x_dnd_frame = NULL; | ||
| 10658 | } | ||
| 10659 | } | ||
| 10660 | |||
| 10569 | /* Handles the XEvent EVENT on display DPYINFO. | 10661 | /* Handles the XEvent EVENT on display DPYINFO. |
| 10570 | 10662 | ||
| 10571 | *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events. | 10663 | *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events. |
| @@ -11006,6 +11098,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 11006 | } | 11098 | } |
| 11007 | } | 11099 | } |
| 11008 | 11100 | ||
| 11101 | if (event->xproperty.window == dpyinfo->root_window | ||
| 11102 | && (event->xproperty.atom == dpyinfo->Xatom_net_client_list_stacking | ||
| 11103 | || event->xproperty.atom == dpyinfo->Xatom_net_current_desktop) | ||
| 11104 | && x_dnd_in_progress) | ||
| 11105 | x_dnd_update_state (dpyinfo); | ||
| 11106 | |||
| 11009 | x_handle_property_notify (&event->xproperty); | 11107 | x_handle_property_notify (&event->xproperty); |
| 11010 | xft_settings_event (dpyinfo, event); | 11108 | xft_settings_event (dpyinfo, event); |
| 11011 | goto OTHER; | 11109 | goto OTHER; |
| @@ -11219,6 +11317,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 11219 | if (xg_is_menu_window (dpyinfo->display, event->xmap.window)) | 11317 | if (xg_is_menu_window (dpyinfo->display, event->xmap.window)) |
| 11220 | popup_activated_flag = 1; | 11318 | popup_activated_flag = 1; |
| 11221 | #endif | 11319 | #endif |
| 11320 | |||
| 11321 | if (x_dnd_in_progress) | ||
| 11322 | x_dnd_update_state (dpyinfo); | ||
| 11222 | /* We use x_top_window_to_frame because map events can | 11323 | /* We use x_top_window_to_frame because map events can |
| 11223 | come for sub-windows and they don't mean that the | 11324 | come for sub-windows and they don't mean that the |
| 11224 | frame is visible. */ | 11325 | frame is visible. */ |
| @@ -12181,6 +12282,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 12181 | #endif | 12282 | #endif |
| 12182 | 12283 | ||
| 12183 | } | 12284 | } |
| 12285 | |||
| 12286 | if (x_dnd_in_progress) | ||
| 12287 | x_dnd_update_state (dpyinfo); | ||
| 12184 | goto OTHER; | 12288 | goto OTHER; |
| 12185 | 12289 | ||
| 12186 | case ButtonRelease: | 12290 | case ButtonRelease: |
| @@ -12460,6 +12564,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 12460 | break; | 12564 | break; |
| 12461 | 12565 | ||
| 12462 | case CirculateNotify: | 12566 | case CirculateNotify: |
| 12567 | if (x_dnd_in_progress) | ||
| 12568 | x_dnd_update_state (dpyinfo); | ||
| 12463 | goto OTHER; | 12569 | goto OTHER; |
| 12464 | 12570 | ||
| 12465 | case CirculateRequest: | 12571 | case CirculateRequest: |
| @@ -18801,6 +18907,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 18801 | ATOM_REFS_INIT ("_NET_WM_FRAME_DRAWN", Xatom_net_wm_frame_drawn) | 18907 | ATOM_REFS_INIT ("_NET_WM_FRAME_DRAWN", Xatom_net_wm_frame_drawn) |
| 18802 | ATOM_REFS_INIT ("_NET_WM_USER_TIME", Xatom_net_wm_user_time) | 18908 | ATOM_REFS_INIT ("_NET_WM_USER_TIME", Xatom_net_wm_user_time) |
| 18803 | ATOM_REFS_INIT ("_NET_WM_USER_TIME_WINDOW", Xatom_net_wm_user_time_window) | 18909 | ATOM_REFS_INIT ("_NET_WM_USER_TIME_WINDOW", Xatom_net_wm_user_time_window) |
| 18910 | ATOM_REFS_INIT ("_NET_CLIENT_LIST_STACKING", Xatom_net_client_list_stacking) | ||
| 18804 | /* Session management */ | 18911 | /* Session management */ |
| 18805 | ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID) | 18912 | ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID) |
| 18806 | ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop) | 18913 | ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop) |
diff --git a/src/xterm.h b/src/xterm.h index ed612c3c1e9..2a11f87e167 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -550,7 +550,7 @@ struct x_display_info | |||
| 550 | Xatom_net_workarea, Xatom_net_wm_opaque_region, Xatom_net_wm_ping, | 550 | Xatom_net_workarea, Xatom_net_wm_opaque_region, Xatom_net_wm_ping, |
| 551 | Xatom_net_wm_sync_request, Xatom_net_wm_sync_request_counter, | 551 | Xatom_net_wm_sync_request, Xatom_net_wm_sync_request_counter, |
| 552 | Xatom_net_wm_frame_drawn, Xatom_net_wm_user_time, | 552 | Xatom_net_wm_frame_drawn, Xatom_net_wm_user_time, |
| 553 | Xatom_net_wm_user_time_window; | 553 | Xatom_net_wm_user_time_window, Xatom_net_client_list_stacking; |
| 554 | 554 | ||
| 555 | /* XSettings atoms and windows. */ | 555 | /* XSettings atoms and windows. */ |
| 556 | Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr; | 556 | Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr; |